如何在通用函数中使用的C#泛型类中找到基础类型?

pae*_*bal 3 c# generics

假设我有一个C#类型:

class MyType<T>
{
   T Value { get; set; }
   // etc.
}
Run Code Online (Sandbox Code Playgroud)

还有一些特殊的类型:

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


class MyTypeDate : MyType<Date>
{
   // etc.
}
Run Code Online (Sandbox Code Playgroud)

我想编写一个通用的功能,我就能操纵(甚至创建)类型的对象MyTypeStringMyTypeDate,并在同一时间返回/修改底层类型值(stringDate).

我目前的解决方案是这样的:

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 ;
}
Run Code Online (Sandbox Code Playgroud)

但是这个解决方案对我来说太冗长了,因为调用方法,我需要提供所有类型,包括主体和底层类型:

MyTypeString myTypeString = null ;
string value ;

value = Foo<MyTypeString, string>(ref myTypeString, "Hello World") ;
Run Code Online (Sandbox Code Playgroud)

在C#中是否有办法使下一行成为可能?

value = Foo<MyTypeString>(ref myTypeString, "Hello World") ;
Run Code Online (Sandbox Code Playgroud)

甚至 :

value = Foo(ref myTypeString, "Hello World") ;
Run Code Online (Sandbox Code Playgroud)

???

PS:MyTypeString是一个通用的string,所以我有预感MyTypeString应该能够给我它的底层类型,但虽然我知道如何在C++中做,我不知道如何在C#中做到,或者即使它是可能.

PPS:我知道,这个例子很愚蠢,但是真正的代码中有一个Setter和一个Getter,因此解释了Foo的"set and get"外观和感觉.

编辑

如上所述,我混合了我的Getter/Setter来问这个问题,但没有意识到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 ;
}
Run Code Online (Sandbox Code Playgroud)

错误(On Monodevelop for Ubuntu 10.10,即C#3.5)是:

错误CS0411:无法从用法推断出方法"MyType.Get(ref T)"的类型参数.尝试明确指定类型参数(CS0411)

但我猜Magnus的答案可以帮助我,或者我会更改Getter的原型以将返回的值作为第二个out参数.

oxi*_*min 6

C#在泛型方法中类型推断,所以你可以只写

value = Foo(ref myTypeString, "hello world");
Run Code Online (Sandbox Code Playgroud)

使用当前的解决方案.


Mag*_*nus 5

oxilumin 是对的,您当前的解决方案已经按您想要的方式工作。但要回答有关如何获取底层泛型类型的问题:

var type = p_variable.GetType().BaseType.GetGenericArguments()[0];
Run Code Online (Sandbox Code Playgroud)