c# - 接口(interface)需要名为 "Item"的索引器但无法实现?

标签 c# .net vb.net interface indexer

我正在尝试在 ESPRIT api 中实现一个类的接口(interface),该接口(interface)需要一个名为“Item”的索引器。 (我猜接口(interface)来自 VB.NET,但我没有源代码。)显然,“Item[index]”索引器默认由编译器自动生成,但我收到以下错误:

Errors

我意识到 [System.Runtime.CompilerServices.IndexerName("Item")] 是多余的;它只是为了明确地证明 Item 已生成并且错误仍然存​​在。

尝试实现 public ToolBarControl Item[int index] 会破坏类其余部分的所有内容。

Edit1:第三个屏幕截图显示了 IToolBar.this,但我确实尝试了 IToolBar.Item 并得到了上述结果。

看起来我不是第一个请求命名迭代器的人,但我认为生成的命名索引器应该满足要求。 https://github.com/dotnet/csharplang/issues/471

如何实现这个索引器来满足接口(interface)?


注意:为了完整性、 future 的故障排除和回答评论中提出的问题,我正在进行以下编辑,但我已经知道这个特定实例的解决方案正在实现 get_Item(int index) 如已接受的答案中所述。

Edit2:回答“visual studio 建议什么?”如您所见,它在进行替换之前就知道 Index 会出错,因为 Item 上没有定义 Index 参数(我已经对此进行了测试,但确实失败了。)其他两个自动实现选项均无效。 Visual Studio suggestion

Edit3:在对象浏览器中,IToolBar 中,Item[int] 定义为:Item definition

最佳答案

C# 可以通过 get_Item 接口(interface)满足 .Item 'indexer'。这是因为在 IL 编译期间如何生成 Property/Index getter 和 setter。

以下是 CLI Specification 中的描述方式:

I.10.4 Naming patterns

For Properties:

An individual property is created by deciding on the type returned by its getter method and the types of the getter’s parameters (if any). Then, two methods are created with names based on the name of the property and these types. For the examples below we define two properties: Name takes no parameters and returns a System.String, while Item takes a System.Object parameter and returns a System.Object. Item is referred to as an indexed property, meaning that it takes parameters and thus can appear to the user as through it were an array with indices.

PropertyGet, used to read the value of the property
   Pattern: <PropType> get_<PropName> (<Indices>)
   Example: System.String get_Name ();
   Example: System.Object get_Item (System.Object key);
PropertySet, used to modify the value of the property
   Pattern: void set_<PropName> (<Indices>, <PropType>)
   Example: void set_Name (System.String name);
   Example: void set_Item (System.Object key, System.Object value); 

因此,您应该能够满足索引器使用如下内容实现它的条件:

public class ManagedEspritToolbar : Esprit.Toolbar
{
    public ToolbarControl get_Item(int index) => Toolbar[index];
}

为了对此进行测试,您可以在 VB.NET 中创建一个简单的界面:

Public Interface IVBNetInterface
    Property Item(index As Integer) As String
End Interface

然后在 C# 中的新类上实现接口(interface)。请注意,当允许 IDE 自动实现接口(interface)时,它如何默认为 get_Item/set_Item 访问器:

public class CSharpClass : IVBNetInterface
{
    public string get_Item(int index)
    {
        throw new NotImplementedException();
    }

    public void set_Item(int index, string Value)
    {
        throw new NotImplementedException();
    }
}

读取接口(interface)生成的 IL 可确认此行为:

enter image description here


VB.NET 的默认属性怎么样?

在 VB.NET 中,有一个 Default 属性装饰器,它本质上是在类上声明索引器的机制:

Public Interface IVBNetInterface
    Default Property Item(index As Integer) As String
End Interface

当它在 VB.NET 类/接口(interface)上正确实现时,标准 C# this[int] 索引实现将起作用。因此,get_Item 变通方法只有在默认属性正确应用于目标索引属性时才是真正需要的。请注意在应用此属性后调查 IL 代码时添加的 System.Reflection.DefaultMemberAttribute 属性:

enter image description here


改进使用:

为了避开使用Default修饰符编写的底层类/接口(interface),您可以显式实现接口(interface)索引器,这允许在类:

public class CSharpClass : IVBNetInterface
{
    public string this[int index]
    {
        get => throw new NotImplementedException();
        set => throw new NotImplementedException();
    }

    #region IVBNetInterface

    string IVBNetInterface.get_Item(int index) => this[index];

    void IVBNetInterface.set_Item(int index, string value) => this[index] = value;

    #endregion
}

如果您希望通过典型索引器推断类的用法同时仍满足底层 Interface.Item 要求,这可能是首选方法。

关于c# - 接口(interface)需要名为 "Item"的索引器但无法实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51975202/

相关文章:

c# - 拆分容器控件是否自动调整窗体大小?

asp.net - 隐藏/显示的 AsyncFileUpload 控件不会触发服务器端 UploadedComplete 事件

vb.net - VB 2008 中的数据类型不匹配

javascript - 只更新折线而不是整个 map

c# - 寻找 .NET 数据访问层

c# - 如何在unity中请求Camera的运行时权限?

c# - 持久集合和标准集合接口(interface)

c# - Azure LDAP 与 DirectoryEntry "the server is not operational"错误 C#

.net - 在 vb.net 中读取非常大的文本文件时出现内存不足错误

c# - 在linq查询后检查实体是否为空