开发者

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

开发者 https://www.devze.com 2023-03-02 02:34 出处:网络
Let\'s say I have a C# type : class MyType<T> { T Value { get; set; } // etc. } And some specialized types :

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") ;

???

P.S.: 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.

P.P.S.: 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, i.e. 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?

0

精彩评论

暂无评论...
验证码 换一张
取 消