简体   繁体   中英

How can I use a generic type's type argument as the type of a method parameter?

There are 1 base-class and 2 sub-class:

class A<T> { }
class B : A<int> { }
class C : A<string> { }

I want use the method test like this:

void test<T>(? param)
{
    // Do something, need to use param, no returns
}
void main()
{
    test<B>(1);        // ok!
    test<B>("1");      // Error!

    test<C>("1");      // ok!
    test<C>(1);        // Error!
}

I want to write only one generic type T (which in this case: B or C), then I get generic type parameters to limit param (which in this case: int or string).

The key is to limit param according to T .

How do I write the method test ?

PS: A more specific example:

namespace T
{
    abstract class A<T>
    {
        public abstract void OnCreate(T param);
    }
    class B : A<int>
    {
        public override void OnCreate(int score)
        {
            int r = score + 1;
            Console.WriteLine(r);
        }
    }
    class C : A<string>
    {
        public override void OnCreate(string msg)
        {
            string r = $"msg:{msg}";
            Console.WriteLine(r);
        }
    }

    class Program
    {

        static void Main()
        {
            // already initialized elsewhere
            var b = new B();
            var c = new C();

            // Solution 1:
            b.OnCreate(1);
            c.OnCreate("this is a msg");

            // Solution 2:
            // I want to use method "run" to achieve solution 1, but I don't know how to write "run"
            run<B>(b, 1);
            run<C>(c, "this is a msg");
            // I want to limit param, if I write wrong type, then Error:
            run<B>(c, 1);       // Error!
            run<B>(b, "1");     // Error!    
            run<C>(c, 222);     // Error!
        }

        static void run<T>(T ins, ?? param) where ??
        {
            // Do Something
            Console.WriteLine("Use method run start");

            ins.OnCreate(param);

            // Do Something
            Console.WriteLine("Use method run end");
        }
    }
}

In this example, I want to use Solution-2 instead of Solution-1.

You can do write the method in the A class:

public static void Main()
{
    new B().test(1);
    new C().test("1");
}


abstract class A<T> {
   public void test(T value){
       Console.WriteLine(value);
   }
}
class B : A<int> {  }
class C : A<string> { }

You can use this:

static void test<TInstance, TParam>(TParam param)
where TInstance : A<TParam>
{
}

test<B, int>(1);
test<C, string>("1");

You must specify two generic parameters because one is for the type and one is for the parameter that is the same of the generic parameter of the type.

There is no way yet to infer TParam from TInstance, as I know, unless using reflexion...

If you want to restrict T and TParam you can add some constraints like these:

class A<T> 
where T : IComparable, IConvertible
{ 
}

static void test<TInstance, TParam>(TParam param)
where TInstance : A<TParam>
where TParam : IComparable, IConvertible
{
}

Hence it only allows numbers and strings as well as any type that implements these interfaces.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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