简体   繁体   中英

How to find the underlying type in a C# generic class to be used in a generic function?

Let's say I have a C# type:

class MyType<T>
{
   T Value { get; set; }
   // etc.
}

And some specialized types:

class MyTypeString : MyType<string>
{
   // etc.
}


class MyTypeDate : MyType<Date>
{
   // etc.
}

I want to write a generic function where I will be able to manipulate (and even create) objects of type MyTypeString or MyTypeDate , and at the same time return/modify the underlying type value ( string or Date ).

My current solution is something like:

T_Underlying Foo<T, T_Underlying>(ref T p_variable, T_Underlying p_value)
        where T : MyType<T_Underlying>, new()
{
    if(p_variable == null)
    {
        p_variable = new T() ;
    }

    p_variable.Value = p_value ;

    return p_value ;
}

But this solution is too much verbose for my taste, as to call the method, I need to provide all types, both the principal and the underlying type:

MyTypeString myTypeString = null ;
string value ;

value = Foo<MyTypeString, string>(ref myTypeString, "Hello World") ;

Is there a way in C# to make the following line possible?

value = Foo<MyTypeString>(ref myTypeString, "Hello World") ;

Or even:

value = Foo(ref myTypeString, "Hello World") ;

???

PS: MyTypeString is a generic on string , so I have a hunch MyTypeString should be able to give me its underlying type, but while I know how to do it in C++, I don't know how to do it in C#, or even if it is possible.

PPS: The example is dumb, I know, but in the real code have both a Setter and a Getter, thus explaining the "set and get" look and feel of Foo.

Edit

As written above, I mixed both my Getter/Setter to ask this question, without realizing the problem was with the Getter:

T_Underlying Get<T, T_Underlying>(ref T p_variable)
        where T : MyType<T_Underlying>, new()
{
    if(p_attributeMember == null)
    {
        return default(T_Underlying) ;
    }

    return p_attributeMember.Value ;
}

The error (On Monodevelop for Ubuntu 10.10, ie C# 3.5) was:

Error CS0411: The type arguments for method `MyType.Get(ref T)' cannot be inferred from the usage. Try specifying the type arguments explicitly (CS0411)

But I guess Magnus's answer could help me there, or I would change the prototype of the Getter to put the returned value as second out parameter.

C# has Type inference in generics method so you can write just

value = Foo(ref myTypeString, "hello world");

using your current solution.

oxilumin is right, your current solution already works as you want. But to answer your question on how to get the underlying generic type:

var type = p_variable.GetType().BaseType.GetGenericArguments()[0];

Have you tried using the typeof keyword to get the type?

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