简体   繁体   English

泛型类型的索引器约束

[英]Indexer constraint on generic types

Is it possible to create a generic class/method where the type must have an indexer? 是否可以创建一个类型必须具有索引器的泛型类/方法?

My thought was to make the following two extension methods work on any type which uses an indexer for getting and setting values, but can't seem to find anything about it. 我的想法是让以下两种扩展方法适用于使用索引器获取和设置值的任何类型,但似乎无法找到任何关于它的内容。 Only stuff about making the indexer itself generic, which is not what I'm after... 只有关于使索引器本身通用的东西,这不是我追求的......

    public static T GetOrNew<T>(this HttpSessionStateBase session, string key) where T : new()
    {
        var value = (T) session[key];
        return ReferenceEquals(value, null) 
            ? session.Set(key, new T()) 
            : value;
    }

    public static T Set<T>(this HttpSessionStateBase session, string key, T value)
    {
        session[key] = value;
        return value;
    }

There is no way to apply a generic constraint that the generic type argument have an indexer (or any operator). 无法应用泛型类型参数具有索引器(或任何运算符)的泛型约束。 The best that you can do is create an interface with that restriction and restrict the generic argument to implementing that interface. 您可以做的最好的事情是创建具有该限制的接口,并限制泛型参数以实现该接口。

Servy has it. Servy有它。 You can't require that the type have an indexer, but you can require that the type implements an interface that exposes an indexer. 您不能要求该类型具有索引器,但您可以要求该类型实现公开索引器的接口。 IList and IDictionary , and their generic counterparts, are the primary built-in interfaces that expose indexers, with integer and string index values respectively. IListIDictionary及其通用对应物是主要的内置接口,它们分别使用整数和字符串索引值来公开索引器。 Unfortunately, a few built-in types, like HttpSessionState, expose indexers of their own accord without implementing an interface identifying that they do so. 不幸的是,一些内置类型(如HttpSessionState)会自动公开索引器,而不会实现识别它们的接口。

You can also define your own indexed interface to apply to any type you control: 您还可以定义自己的索引接口以应用于您控制的任何类型:

public interface IIndexable<TKey, TVal>
{
   TVal this[TKey key]{get;}
}

So, best-case, you could implement three overloads of these methods: 所以,最好的情况是,你可以实现这些方法的三个重载:

public static TElem GetOrNew<TList, TElem>(this TList collection, int key) 
    where TList : IList<TElem>, TElem:new()
{
    ...
}

public static TElem Set<TList, TElem>(this TList collection, int key, TElem value) 
    where TList: IList<TElem>
{
    ...
}

public static TVal GetOrNew<TDict, TKey, TVal>(this TDict collection, TKey key) 
    where TDict : IDictionary<TKey, TVal>, TVal : new()
{
    ...
}

public static TVal Set<TDict, TKey, TVal>(this TDict collection, TKey key, TVal value) 
    where TDict : IDictionary<TKey, TVal>
{
    ...
}

public static TVal GetOrNew<TColl, TKey, TVal>(this TDict collection, TKey key) 
    where TColl : IIndexable<TKey, TVal>, TVal: new()
{
    ...
}

public static TVal Set<TColl, TKey, TVal>(this TDict collection, TKey key, TVal value) 
    where TColl : IIndexable<TKey, TVal>
{
    ...
}

... which would allow you to use this method set on the 90th percentile of objects with an indexer (including Array, which for practical purposes implements IList). ...这将允许您使用索引器(包括Array,实际上用于实现IList)在第90百分位的对象上使用此方法集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM