为什么不能在.NET中创建通用索引器?
以下代码抛出编译器错误:
public T this<T>[string key]
{
get { /* Return generic type T. */ }
}
这是否意味着您无法为通用成员集合创建通用索引器?
答案 0 :(得分:27)
这是一个有用的地方。假设您有一个强类型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];
}
答案 1 :(得分:18)
属性在C#2.0 / 3.0中不能通用,因此您不能拥有通用索引器。
答案 2 :(得分:16)
我不知道为什么,但索引器只是语法糖。写一个通用的方法,你将获得相同的功能。例如:
public T GetItem<T>(string key)
{
/* Return generic type T. */
}
答案 3 :(得分:11)
你可以;只需从您的声明中删除<T>
部分,它就可以正常工作。即。
public T this[string key]
{
get { /* Return generic type T. */ }
}
(假设您的类是通用的,名为T
的类型参数。)
答案 4 :(得分:2)
我喜欢没有分发索引器的能力 直接引用“索引”项。我写了一个简单的 “回拨”下面的索引器类......
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);
}
如果你想监视访问权限,就像一个冠军 您的列表或在访问某些内容时执行任何特殊操作。
答案 5 :(得分:1)
我能想到的唯一可以使用的就是这些:
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及其动态关键字。
答案 6 :(得分:0)
在最近的C-sharp中,您可以将返回类型声明为&#34; dynamic&#34;。这与使用&#34; object&#34;相同。除了C#运行时允许你在代码中使用它,就好像它是你认为的那样,然后在运行时检查以确保你是对的......