为什么不能在.NET中定义通用索引器?

Igo*_*aya 45 .net c# generics

为什么不能在.NET中创建通用索引器?

以下代码抛出编译器错误:

   public T this<T>[string key]
   {
      get { /* Return generic type T. */ }
   }
Run Code Online (Sandbox Code Playgroud)

这是否意味着您无法为通用成员集合创建通用索引器?

Sam*_*ell 28

这是一个有用的地方.假设你有一个强类型OptionKey<T>的声明选项.

public static class DefaultOptions
{
    public static OptionKey<bool> SomeBooleanOption { get; }
    public static OptionKey<int> SomeIntegerOption { get; }
}
Run Code Online (Sandbox Code Playgroud)

通过IOptions界面公开选项的位置:

public interface IOptions
{
    /* since options have a default value that can be returned if nothing's
     * been set for the key, it'd be nice to use the property instead of the
     * pair of methods.
     */
    T this<T>[OptionKey<T> key]
    {
        get;
        set;
    }

    T GetOptionValue<T>(OptionKey<T> key);
    void SetOptionValue<T>(OptionKey<T> key, T value);
}
Run Code Online (Sandbox Code Playgroud)

然后,代码可以使用通用索引器作为一个很好的强类型选项存储:

void Foo()
{
    IOptions o = ...;
    o[DefaultOptions.SomeBooleanOption] = true;
    int integerValue = o[DefaultOptions.SomeIntegerOption];
}
Run Code Online (Sandbox Code Playgroud)

  • 现在是 2021 年了,我们只有通用方法,但仍然没有通用索引器...... (5认同)

Kev*_*Kev 18

属性在C#2.0/3.0中不能通用,因此您不能拥有通用索引器.

  • 你有这方面的任何东西的链接吗?我在"新功能"文档中看不到它. (2认同)
  • mmmm ......我想我找到了你要找的链接.http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=352188对我来说似乎不可思议的是,微软表示它不是一个有用的功能,但已经实现了一些解决方法扩展器(ieDataRowExtender) (2认同)
  • 2016年,c#6没有通用索引器.https://github.com/dotnet/roslyn/issues/523 (2认同)

dav*_*nes 17

我不知道为什么,但索引器只是语法糖.写一个通用的方法,你将获得相同的功能.例如:

   public T GetItem<T>(string key)
   {
      /* Return generic type T. */
   }
Run Code Online (Sandbox Code Playgroud)


Gre*_*ech 11

您可以; 只需<T>从声明中删除该部分,它就可以正常工作.即

public T this[string key]
{
   get { /* Return generic type T. */ }
}
Run Code Online (Sandbox Code Playgroud)

(假设您的类是通用的,名为类型参数T).

  • 除非您在类级别定义<T>,否则这将无效. (5认同)
  • @Igor - 这就是为什么我说"假设你的类是通用的名为T的类型参数".问题并没有表明类型参数应该与容器不同(在任何情况下,这都是一个非常不寻常的设计!). (4认同)
  • @Greg ......它有多不寻常?以DataRow中的Field <>泛型方法为例.他们所做的是通过泛型方法取消装箱,因为通过通用索引器是不可能的. (2认同)

Ant*_*lev 3

我能想到的唯一可以使用的是以下内容:

var settings = ConfigurationSection.AppSettings;
var connectionString = settings<string>["connectionString"];
var timeout = settings<int>["timeout"];
Run Code Online (Sandbox Code Playgroud)

但这实际上并不能给你带来任何东西。您刚刚用尖括号替换了圆括号(如(int)settings["timeout"]),但没有像您可以自由执行的那样获得额外的类型安全性

var timeout = settings<int>["connectionString"];
Run Code Online (Sandbox Code Playgroud)

如果您有强类型但非静态类型的东西,您可能需要等到 C# 4.0 及其动态关键字。

  • 嗯,实际上 settings&lt;int&gt; 语法更可取。C 风格的强制转换通常会迫使您包含额外的括号。 (7认同)