为什么不能在.NET中定义generics索引器?
为什么不能在.NET中创build一个通用索引器?
下面的代码抛出一个编译器错误:
public T this<T>[string key] { get { /* Return generic type T. */ } }
这是否意味着您不能为通用成员集合创build通用索引器?
我能想到的唯一的东西就是这样:
var settings = ConfigurationSection.AppSettings; var connectionString = settings<string>["connectionString"]; var timeout = settings<int>["timeout"];
但是这实际上并没有给你买任何东西。 你刚刚用尖括号replace了圆括号(如(int)settings [“timeout”]),但没有收到额外的types安全性,你可以自由地做
var timeout = settings<int>["connectionString"];
如果您有强烈的但没有静态types的东西,那么您可能要等到C#4.0及其dynamic关键字。
这是一个有用的地方。 假设你有一个强types的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); }
然后代码可以使用通用索引器作为一个很好的强types选项存储:
void Foo() { IOptions o = ...; o[DefaultOptions.SomeBooleanOption] = true; int integerValue = o[DefaultOptions.SomeIntegerOption]; }
在C#2.0 / 3.0中属性不能是通用的,所以你不能拥有一个通用的索引器。
我不知道为什么,但分度器只是语法糖。 写一个通用的方法,而你会得到相同的function。 例如:
public T GetItem<T>(string key) { /* Return generic type T. */ }
您可以; 只要从你的声明中删除<T>
部分,它会正常工作。 即
public T this[string key] { get { /* Return generic type T. */ } }
(假设你的类是一个名字为T
的types参数)。
我喜欢有一个索引器的能力,而不用直接引用“索引”项。 我写了一个简单的“callback”索引类下面…
R =从索引器返回的typesP =传入的types到索引器中
所有的索引器真正做的是将操作传递给部署者,并允许他们pipe理实际发生和返回。
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); }
像冠军一样工作,特别是如果您想要监视对列表的访问,或者在访问某些内容时执行任何特殊操作。