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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/494827/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 05:36:46  来源:igfitidea点击:

Why it is not possible to define generic indexers in .NET?

c#.netgenerics

提问by Igor Zelaya

Why can't you create a generic indexer in .NET?

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

the following code throws a compiler error:

以下代码引发编译器错误:

   public T this<T>[string key]
   {
      get { /* Return generic type T. */ }
   }

Does this mean you can't create a generic indexer for a generic member collection?

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

采纳答案by Anton Gogolev

The only thing I can think of this can be used is something along these lines:

我能想到的唯一可以使用的东西是这样的:

var settings = ConfigurationSection.AppSettings;
var connectionString = settings<string>["connectionString"];
var timeout = settings<int>["timeout"];

But this doesn't actually buy you anything. You've just replaced round parentheses (as in (int)settings["timeout"]) with angle brackets, but received no additional type safety as you can freely do

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

var timeout = settings<int>["connectionString"];

If you have something that's strongly but not statically typed, you might want to wait until C# 4.0 with its dynamickeyword.

如果你有一些强类型但不是静态类型的东西,你可能想要等到 C# 4.0 使用它的dynamic关键字。

回答by Greg Beech

You can; just drop the <T>part from your declaration and it will work fine. i.e.

你可以; 只需<T>从您的声明中删除该部分,它就会正常工作。IE

public T this[string key]
{
   get { /* Return generic type T. */ }
}

(Assuming your class is generic with a type parameter named T).

(假设您的类是具有名为 的类型参数的泛型T)。

回答by davogones

I don't know why, but indexers are just syntactic sugar. Write a generic method instead and you'll get the same functionality. For example:

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

   public T GetItem<T>(string key)
   {
      /* Return generic type T. */
   }

回答by Kev

Properties can't be generic in C#2.0/3.0 so therefore you can't have a generic indexer.

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

回答by Sam Harwell

Here's a place where this would be useful. Say you have a strongly-typed OptionKey<T>for declaring options.

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

public static class DefaultOptions
{
    public static OptionKey<bool> SomeBooleanOption { get; }
    public static OptionKey<int> SomeIntegerOption { get; }
}

Where options are exposed through the IOptionsinterface:

通过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);
}

Code could then use the generic indexer as a nice strongly-typed options store:

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

void Foo()
{
    IOptions o = ...;
    o[DefaultOptions.SomeBooleanOption] = true;
    int integerValue = o[DefaultOptions.SomeIntegerOption];
}

回答by Stuart Peacock

I like the ability to have an indexer without handing out a direct reference to the "indexed" item. I wrote a simple "call back" Indexer class below ...

我喜欢无需直接引用“索引”项即可拥有索引器的能力。我在下面写了一个简单的“回调”索引器类......

R = the returned type from the indexer P = the passed type into the indexer

R = 从索引器返回的类型 P = 传递到索引器的类型

All the indexer really does is pass the operations to the deployer and allow them to manage what actually occurs and gets returned.

索引器真正做的就是将操作传递给部署者,并允许他们管理实际发生和返回的内容。

public class GeneralIndexer<R,P>
    {
        // Delegates
        public delegate R gen_get(P parm);
        public delegate void gen_set(P parm, R value);
        public delegate P[] key_get();

        // Events
        public event gen_get GetEvent;
        public event gen_set SetEvent;
        public event key_get KeyRequest;

        public R this[P parm]
        {
            get { return GetEvent.Invoke(parm); }
            set { SetEvent.Invoke(parm, value); }
        }

        public P[] Keys
        {
            get
            {
                return KeyRequest.Invoke();
            }
        }

    }

To use it in a program or class:

在程序或类中使用它:

private GeneralIndexer<TimeSpan, string> TimeIndex = new GeneralIndexer<TimeSpan,string>();

{
            TimeIndex.GetEvent += new GeneralIndexer<TimeSpan, string>.gen_get(TimeIndex_GetEvent);
            TimeIndex.SetEvent += new GeneralIndexer<TimeSpan, string>.gen_set(TimeIndex_SetEvent);
            TimeIndex.KeyRequest += new GeneralIndexer<TimeSpan, string>.key_get(TimeIndex_KeyRequest);

}

works like a champ especially if you want to monitor access to your list or do any special operations when something is accessed.

像冠军一样工作,特别是如果您想监视对列表的访问或在访问某些内容时执行任何特殊操作。

回答by Jeffrey Kesselman

In recent C-sharp you can declare the return type as "dynamic". This is the same as using "object" except that the C# runtime will allow you to use it in code as if it was the type you think it is and then check at run-time to be sure you were right...

在最近的 C-sharp 中,您可以将返回类型声明为“动态”。这与使用“对象”相同,只是 C# 运行时将允许您在代码中使用它,就好像它是您认为的类型,然后在运行时检查以确保您是正确的...