Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在VB.NET中创建可从C使用的索引器#_C#_.net_Vb.net_Indexer_Language Interoperability - Fatal编程技术网

C# 在VB.NET中创建可从C使用的索引器#

C# 在VB.NET中创建可从C使用的索引器#,c#,.net,vb.net,indexer,language-interoperability,C#,.net,Vb.net,Indexer,Language Interoperability,我可以在VB.NET中创建一个类,该类可以从C#中使用,如下所示: myObject.Objects[index].Prop = 1234; 当然,我可以创建一个返回数组的属性。但要求索引是基于1的,而不是基于0的,因此该方法必须以某种方式映射索引: 我试着这样做,但C#告诉我我不能直接称之为: Public ReadOnly Property Objects(ByVal index As Integer) As ObjectData Get If

我可以在VB.NET中创建一个类,该类可以从C#中使用,如下所示:

myObject.Objects[index].Prop = 1234;
当然,我可以创建一个返回数组的属性。但要求索引是基于1的,而不是基于0的,因此该方法必须以某种方式映射索引:

我试着这样做,但C#告诉我我不能直接称之为:

   Public ReadOnly Property Objects(ByVal index As Integer) As ObjectData
        Get
            If (index = 0) Then
                Throw New ArgumentOutOfRangeException()
            End If
            Return parrObjectData(index)
        End Get
    End Property
编辑 抱歉,如果我有点不清楚:

C#只允许我像这样调用此方法

myObject.get_对象(索引).Prop=1234

但不是

myObject.Objects[index].Prop=1234


这就是我想要实现的。

为什么不使用基于0的索引,但给编码器一个基于1的错觉

语法是:

Default Public ReadOnly Property Item(ByVal index as Integer) As ObjectData
  Get
    If (index = 0) Then
      Throw New ArgumentOutOfRangeException()
    End If
    Return parrObjectData(index)
  End Get
End Property
Default
关键字是创建索引器的魔法。不幸的是,C#不支持命名索引器。您必须创建一个自定义集合包装器并返回它

Public ReadOnly Property Objects As ICollection(Of ObjectData)
  Get
    Return New CollectionWrapper(parrObjectData)
  End Get
End Property
其中,
CollectionWrapper
可能如下所示:

Private Class CollectionWrapper
  Implements ICollection(Of ObjectData)

  Private m_Collection As ICollection(Of ObjectData)

  Public Sub New(ByVal collection As ICollection(Of ObjectData))
    m_Collection = collection
  End Sub

  Default Public ReadOnly Property Item(ByVal index as Integer) As ObjectData
    Get
      If (index = 0) Then
        Throw New ArgumentOutOfRangeException()
      End If
      Return m_Collection(index)
    End Get
  End Property

End Class

C#不支持命名索引属性的声明(尽管您可以创建索引器),但您可以通过显式调用setter或getter来访问以其他语言(如VB)声明的索引属性(
get_MyProperty
/
set_MyProperty

您可以使用带有默认索引器的结构在C#中伪造命名索引器:

public class ObjectData
{
}

public class MyClass
{
    private List<ObjectData> _objects=new List<ObjectData>();
    public ObjectsIndexer Objects{get{return new ObjectsIndexer(this);}}

    public struct ObjectsIndexer
    {
        private MyClass _instance;

        internal ObjectsIndexer(MyClass instance)
        {
            _instance=instance;
        }

        public ObjectData this[int index]
        {
            get
            {
                return _instance._objects[index-1];
            }
        }
    }
}

void Main()
{
        MyClass cls=new MyClass();
        ObjectData data=cls.Objects[1];
}
公共类ObjectData
{
}
公共类MyClass
{
私有列表_objects=新列表();
public ObjectsIndexer对象{get{返回新的ObjectsIndexer(this);}
公共结构对象索引
{
私有MyClass_实例;
内部ObjectsIndex(MyClass实例)
{
_实例=实例;
}
公共对象数据此[int索引]
{
得到
{
返回_实例._对象[index-1];
}
}
}
}
void Main()
{
MyClass cls=新的MyClass();
ObjectData data=cls.Objects[1];
}

如果这是一个好主意,则是另一个问题。

方法签名应该是什么样子?与它一样,这应该是唯一应该更改的行。除了删除(index=0)if语句块之外,我的问题是,对于当前的方法签名,VB.NET不允许我像myObject一样调用该方法。Objects[index]
Default
是您缺少的关键字。Brian的回答让你明白了。你要求的是一个索引属性,这是C#中无法直接使用的功能。如果我希望该属性有一个除Item之外的名称,你忘记了“property”关键字。需要注意的是,只有当ObjectData对象是类时,这才是一个好的解决方案。如果它是一个结构,您将无法在ObjectsIndex中存储对它的引用(最多您可以获得一个副本)。这使得使用此模式用固定缓冲区包装不安全的结构成为问题,因为不能在类中使用固定缓冲区,也不能让ObjectsIndex指向结构。
public class ObjectData
{
}

public class MyClass
{
    private List<ObjectData> _objects=new List<ObjectData>();
    public ObjectsIndexer Objects{get{return new ObjectsIndexer(this);}}

    public struct ObjectsIndexer
    {
        private MyClass _instance;

        internal ObjectsIndexer(MyClass instance)
        {
            _instance=instance;
        }

        public ObjectData this[int index]
        {
            get
            {
                return _instance._objects[index-1];
            }
        }
    }
}

void Main()
{
        MyClass cls=new MyClass();
        ObjectData data=cls.Objects[1];
}