Generic method with dynamic T

时间:2016-04-15 14:57:12

标签: c# generics

I'm making a small example to check the type of parameter is valid or not.

class A
{
}

class B
{
}

class C
{
}

class D
{
    public void SomeMethod<T>(T t) where T : class
    {
        if (t is A)
        {
            A a = t as A;
        }
        else if (t is B)
        {
            B b = t as B;
        }
    }
}

Then, I can call:

A a = new A();
SomeMethod<A>(a);

B b = new B();
SomeMethod<B>(b);

Now, I want to prevent to passing class C to SomeMethod. What I want to achieve:

C c = new C();
SomeMethod<C>(c); // error

To do that, I've tried:

public void SomeMethod<T>(T t) where T : A
{
    // accept only class A
}

or

public void SomeMethod<T>(T t) where T : B
{
    // accept only class B
}

My question is: how to declare SomeMethod with T can be A or B at the same time? Just like:

public void SomeMethod<T>(T t) where T : A, B
{
    // accept class A and class B
}

2 个答案:

答案 0 :(得分:5)

As Lee has mentioned, this defeats the purpose of generics. To ahieve what you're describing just write overloads for each case

class A { }
class B { }
class C { }

class D
{
    public void SomeMethod(A a)
    {
        //Do stuff with a
    }
    public void SomeMethod(B b)
    {
        //Do stuff with b
    }
}

If you wanted to have a run-time error you could do something like this:

class A { }
class B { }
class C { }    

class D
{
    public void SomeMethod<T>(T t) where T : class
    {
        if (t is A)
        {
            A a = t as A;
        }
        else if (t is B)
        {
            B b = t as B;
        }
        else //if (t is C)
        {
            throw new ArgumentException();
        }
    }
}

Though this is a poor solution. The overload solution is still cleaner and will give a compile-time error.

答案 1 :(得分:0)

It seems like really bad practice but I think you could do

class D
{
    public void SomeMethod<T>(T t) where T : class
    {
        if (t is A)
            A a = t as A;
        else if (t is B)
            B b = t as B;
        else
            throw new Exception("Wrong class type.");
    }
}

This way you can use the method with only classes A and B, and it will throw an error for class C - and others.