C # generic constraint: does the type parameter in the class inherit the type parameter in the method?

I have a generic class on which I define a method that should accept arguments of a different type, but only if another type implements a parameter of the class type. However, this does not compile:

class GenericClass<TClass>
{
    public void DoSomething<TMethod>(TMethod input) where TClass : TMethod
    {
        // ...
    }
}

I get a compiler error on TClassin method restriction. Is there any way to indicate this?

Explanation:
I get the impression that it TMethod : TClassmeans it TMethodshould inherit or implement TClass(depending on whether it is a TClassparticular type or interface). In another, slightly unconventional notation TMethod > TClass(meaning TMethodis a superset TClass).

What I want here is that it TMethodshould only be a valid type if it TClassinherits or implements it, i.e. TClass > TMethod. Will it TMethod : TClassdo it?

(One answer says it TMethod : TClassrequires that TMethodyou can assign from TClass. I'm not sure if this meets my requirements, but if so, please explain in more detail what can be assigned from means, because if it helps me, I probably misunderstood this ...)

+5
source share
4 answers

Summary:

Chris Hannon's answer is basically correct. However, there are hidden tricks involving interfaces and extension methods that can get what you want.

:

, , . Java , Scala : " ". , #, CLR.

, , :

class ImmutableStack<T>
{
    public static ImmutableStack<T> Empty { get { return empty; } }
    private static ImmutableStack<T> empty = new ImmutableStack<T>();
    private T head;
    private ImmutableStack<T> tail;
    public ImmutableStack<T> Pop()
    {
        if (this == empty) throw new Exception();
        return this.tail;
    }
    public ImmutableStack<N> Push(N value) where T : N // not legal
    {
        var result = new ImmutableStack<N>();
        result.head = value;
        result.tail = this; // also not legal
        return result;
    }
}

- :

Tiger tony = new Tiger();
Elephant dumbo = new Elephant();
ImmutableStack<Tiger> tigers = ImmutableStack<Tiger>.Empty;
tigers = tigers.Push<Tiger>(tony);
ImmutableStack<Mammal> mammals = tigers.Push<Mammal>(dumbo);

, , !

#, : -, , -, . ( .)

#, . , , . " ", ! , :

http://blogs.msdn.com/b/ericlippert/archive/2007/12/06/immutability-in-c-part-three-a-covariant-immutable-stack.aspx

+8

, #. , , , - , TMethod: TClass , , TMethod , , TClass.

TMethod "- " , , , . , ? ? , ? , , , Object , , , .

, . A, - A, A? , B B , , B , A.

+4

, TClass . TClass , .

Try...

class GenericClass<TClass>
{
    public void DoSomething<TMethod>(TMethod input) where TMethod : TClass
    {
        // ...
    }
}

, , TMethod TClass.

0

, -, Object .

class GenericClass<TClass>
{
    public void DoSomething(Object input)
    {
        if (input == null) throw new ArgumentNullException("input");
        if (!input.GetType().IsAssignableFrom(typeof(TClass)))
            throw new ArgumentException("Input type must be assignable from " + typeof(TClass).ToString(), "input");
        // ...
    }
}

Please note that this will allow you to enter objects of type Object, as well as (in rare cases with transparent remote proxies) the type of interface that implements TClass. They can also be explicitly excluded.

0
source

All Articles