Indexer constraint on generic types

Is it possible to create a generic class / method in which the type must have an index?

My thought was to do the following two extension methods for any type that uses an index to get and set values, but can't seem to find anything. Just about how to make the indexer itself generic, which is not what I need ...

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

      

+3


source to share


2 answers


It is not possible to enforce a generic constraint that the generic type argument has an index (or any operator). The best you can do is create an interface with this constraint and constrain the generic argument to implement that interface.



+7


source


Servy has it. You cannot require a type to have an index, but you can require a type to implement the interface that the index provides. IList

and IDictionary

, as well as their common counterparts, are primary built-in interfaces that expose integer and string indices respectively. Unfortunately, some built-in types, such as HttpSessionState, expose indexers themselves, without implementing an interface that defines what they do.

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, at best, you can 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 will allow you to use this method set at the 90th percentile of indexed objects (including Array, which IList implements for practical purposes).

+3


source







All Articles