Specifying "any subclass" in a C # type constraint, rather than "one specific subclass",

If I would like to write a method that accepts a variable number "TDerived", where TDerived is any subclass of the "Base" class, is there any way to do this?

The following code only works with one specific subclass specified:

void doStuff<TDerived>(params TDerived[] args) where TDerived : Base
{
    //stuff
}

those. if I

class Super { }
class Sub0 : Super { }
class Sub1 : Super { }

then i can't do

Sub0 s0 = new Sub0();
Sub1 s1 = new Sub1();
doStuff(s0, s1);

since I get "the best overloaded match ... has some invalid arguments".

Regardless of how the compiler handles type constraints and variational functions, this seems (as far as I can tell) completely type safe. I know I can quit, but if it's a safe type, why not let it?

EDIT:

Perhaps a more convincing example:

void doStuff<TDerived>(params SomeReadOnlyCollection<TDerived>[] args) where TDerived : Base
{
    foreach(var list in args)
    {
        foreach(TDerived thing in list)
        {
            //stuff
        }
    }
}
+5
4

TDerived . , , Super, . .

doStuff(new Super[] { s0, s1 });
doStuff<Super>(s0, s1);

, ( ) , IEnumerable<ISuper>, , IEnumerable<T> ( .NET 4). IEnumerable<T> readonly forward-only, , foreach. :

class Program
{
    static void Main()
    {
        var sub0s = new Sub0[] { new Sub0() };
        var sub1s = new List<Sub1> { new Sub1() };
        doStuff(sub0s, sub1s);
    }

    static void doStuff(params IEnumerable<ISuper>[] args)
    {
        foreach (var sequence in args)
        {
            foreach (var obj in sequence)
            {
                Console.WriteLine(obj.GetType());
                // you have the ability to invoke any method or access 
                // any property defined on ISuper
            }
        }
    } 
}

interface ISuper { }
class Super : ISuper { }
class Sub0 : Super { }
class Sub1 : Super { }  

IEnumerable<T> BCL .NET 2.0, T[], List<T>, ReadOnlyCollection<T>, HashSet<T> ..

+6

, doStuff Base. , , generics:

void doStuff(params Base[] args)
{}

- SomeReadOnlyCollection IEnumerable, covariant:

void doStuff(params IEnumerable<Base>[] args)
{
    foreach (var list in args)
    {
        foreach (var thing in list)
        {
        }
    }
}
+6

,

Sub0 s0 = new Sub0();
Sub1 s1 = new Sub1();

Super s0 = new Sub0();
Super s1 = new Sub1();

, Super TDerived.

, , - - .

0

Another alternative that you can use is to simply specify the general parameter explicitly. For instance:

var s0 = new Sub0();
var s1 = new Sub1();

doStuff<Super>(s0, s1);

You should use the same principle in case SomeReadOnlyCollectionit is covariant . For example, IEnumerablea collection like this:

static void doStuff2<TDerived>(params IEnumerable<TDerived>[] args) where TDerived : Super {
    // ...
}

// ...

var l0 = new List<Sub0>();
var l1 = new List<Sub1>();

doStuff2<Super>(l0, l1);
0
source

All Articles