Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.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# 名为“索引器”;项目「;接口要求但不可能实现?_C#_.net_Vb.net_Interface_Indexer - Fatal编程技术网

C# 名为“索引器”;项目「;接口要求但不可能实现?

C# 名为“索引器”;项目「;接口要求但不可能实现?,c#,.net,vb.net,interface,indexer,C#,.net,Vb.net,Interface,Indexer,我试图在ESPRIT api中实现一个类的接口,该接口需要一个名为“Item”的索引器。(我猜该接口来自VB.NET,但我没有源代码。)显然,“Item[index]”索引器默认由编译器自动生成,但我得到以下错误: 我意识到[System.Runtime.CompilerServices.IndexerName(“Item”)]是冗余的;它只是为了明确地证明生成了项,错误仍然存在 试图实现公共工具栏控件项[int index]“splodes类其余部分中的所有内容 编辑1:第三个屏幕截图显示了

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

我意识到
[System.Runtime.CompilerServices.IndexerName(“Item”)]
是冗余的;它只是为了明确地证明生成了
,错误仍然存在

试图实现
公共工具栏控件项[int index]
“splodes类其余部分中的所有内容

编辑1:第三个屏幕截图显示了
IToolBar。这是
但我确实尝试了
IToolBar.Item
,结果如上所述

看起来我不是第一个请求命名迭代器的人,但我认为生成的命名索引器应该满足要求。

如何实现此索引器以满足接口要求


注意:为了完整性、将来的故障排除以及回答评论中提出的问题,我正在进行以下编辑,但我已经知道,这个特定实例的解决方案是按照公认答案中的说明实施
get\u Item(int index)

Edit2:要回答“visual studio建议了什么?”您可以看到,它在进行替换之前就知道,
索引
将出错,因为在
上没有定义
索引
参数(我已经测试过了,它确实失败了)。自动实现的其他两个选项都不起作用。


Edit3:在对象浏览器中,在
IToolBar
内部,
项[int]
被定义为:

问题是没有有效的C语法来声明命名索引器,因此无法使用C满足该接口。有几项要求在C语言中实现命名索引器的请求都被C语言团队忽略或直接拒绝。他们似乎不想在C#中实现此功能。也许如果他们以后改变主意,你可能会有机会

目前,我唯一能想到的方法是创建一个VB.NET库,其中包含一个类,该类实现接口,并充当您自己类的包装器或基类。

C#可以满足这一要求。使用
get\u Item
接口的项“indexer”。这是因为在IL编译期间如何生成属性/索引getter和setter

以下是在中的描述:

I.10.4命名模式 对于属性:

通过确定其getter方法和 getter参数的类型(若有)然后,创建两个基于 属性名称和这些类型。对于下面的示例,我们定义了两个属性:名称 不接受任何参数并返回System.String,而项接受System.Object参数 并返回一个System.Object。项被称为索引属性,这意味着它需要 参数,因此用户可以将其视为带有索引的数组


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

Public Interface IVBNetInterface
    Property Item(index As Integer) As String
End Interface
然后在C#中的一个新类上实现该接口。请注意,当允许IDE自动实现接口时,它是如何默认为
get\u Item/set\u 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();
    }
}
读取接口的生成IL可确认此行为:


那么VB.NET的默认属性呢? 在VB.NET中,有一个
Default
property decorator,它本质上是在类上声明索引器的机制:

Public Interface IVBNetInterface
    Default Property Item(index As Integer) As String
End Interface
当这在VB.NET类/接口上正确实现时,标准的C#
此[int]
索引实现将起作用。因此,只有当默认属性未正确应用于目标索引属性时,
get\u项
解决方法才真正有必要。请注意,在应用IL代码后调查IL代码时,添加了
System.Reflection.DefaultMemberAttribute
属性:


提高使用率: 要绕过未使用
Default
修饰符编写的底层类/接口,可以明确地实现接口索引器,这允许在类上公开传统的C风格索引器:

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
}

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

是否有用于您正在使用的自定义库的API文档?删除您自己的代码后,当您将鼠标悬停在Esprit.Tooolbar上时,Visual Studio建议实现什么?此缺少的成员的接口规范是什么?是否确定
this[]
的返回类型为“ToolBarControl”?如果找不到文档,请在反汇编程序中打开引用,查看它具体在查找什么@Neil可能是对的,它可能需要来自索引器的“object”或“IToolbarControl”。我实现了
get_Item
as
public ToolBarControl get_Item(int index)=>ToolBar.Item[index]
和它(奇怪的是)满足了
项[int]get
要求。想在答案顶部添加一个TLDR简介,基本上说明
get_Item(int index)
可以满足接口的
Item
要求吗?@Still.Tony,我与另一个用VB.NET编写的第三方库合作过,我注意到了一些类似的行为。如果您有一个IL反汇编程序,那么可能值得查看IToolbar以查看底层代码。也许在某个地方用“Esprit”更新您的问题,以便其他人能够找到。
Public Interface IVBNetInterface
    Default Property Item(index As Integer) As String
End 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
}