代码之家  ›  专栏  ›  技术社区  ›  Igor Zelaya

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

  •  42
  • Igor Zelaya  · 技术社区  · 17 年前

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

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

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

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

    7 回复  |  直到 8 年前
        1
  •  1
  •   Anton Gogolev    17 年前

    我能想到的唯一能用的东西是沿着这些线的东西:

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

    但这并不能给你买任何东西。您刚刚用尖括号替换了圆括号(如(int)settings[“timeout”]),但没有收到您可以自由执行的额外类型安全性。

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

    如果有强而非静态类型的内容,您可能需要等到C 4.0及其 动态 关键字。

        2
  •  26
  •   Sam Harwell    14 年前

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

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

    如果选项通过 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);
    }
    

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

    void Foo()
    {
        IOptions o = ...;
        o[DefaultOptions.SomeBooleanOption] = true;
        int integerValue = o[DefaultOptions.SomeIntegerOption];
    }
    
        3
  •  18
  •   erlando    14 年前

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

        4
  •  16
  •   davogones    17 年前

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

       public T GetItem<T>(string key)
       {
          /* Return generic type T. */
       }
    
        5
  •  11
  •   Greg Beech    17 年前

    你可以,放下 <T> 从你的声明中分离出来,它会很好地工作。即

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

    (假设您的类是具有名为 T )

        6
  •  2
  •   Stuart Peacock    13 年前

    我喜欢拥有一个不需要分发的索引器的能力 对“索引”项的直接引用。我写了一个简单的 下面的“回调”索引器类…

    r=从索引器返回的类型 p=传入索引器的类型

    索引器真正做的就是将操作传递给 部署者并允许他们管理实际发生的事情 然后就回来了。

    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();
                }
            }
    
        }
    

    在程序或类中使用它:

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

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

        7
  •  0
  •   Jeffrey Kesselman    8 年前

    在最近的C-Sharp中,您可以将返回类型声明为“dynamic”。这与使用“object”相同,只是C运行时允许您在代码中使用它,就好像它是您认为的类型一样,然后在运行时检查以确保您是正确的…