C# 泛型函数创建基本参数的泛型对象

C# 泛型函数创建基本参数的泛型对象,c#,generics,inheritance,C#,Generics,Inheritance,我有以下代码: public class Foo { public void DoSomething() { DoSomething(this); } private static void DoSomething<T>(T obj) { var generic = new Generic<T>(); } } public class Bar : Foo { // properti

我有以下代码:

public class Foo
{
    public void DoSomething()
    {
        DoSomething(this);
    }

    private static void DoSomething<T>(T obj)
    {
        var generic = new Generic<T>();
    }
}

public class Bar : Foo
{
    // properties/methods
}

public class Generic<T>
{
    // properties/methods
}

public class Test
{
    public void TestMethod()
    {
        var bar = new Bar();
        bar.DoSomething(); // instantiates Generic<Foo> instead of Generic<Bar>
    }
}
公共类Foo
{
公共无效剂量测定法()
{
DoSomething(这个);
}
专用静态空隙剂量仪(T obj)
{
var generic=new generic();
}
}
公共类酒吧:富
{
//属性/方法
}
公共类泛型
{
//属性/方法
}
公开课考试
{
公共void TestMethod()
{
var bar=新的bar();
bar.DoSomething();//实例化泛型而不是泛型
}
}

是否可以使用当前类型而不是基类型从派生方法实例化泛型类?

Foo中
this
的编译时类型。DoSomething
只是
Foo
,因此编译器只能推断类型参数为
Foo

根据执行时间类型使其执行的最简单方法可能是:

DoSomething((dynamic) this);

或者,您可以自己使用反射调用它。

问题是它正在将
T
解析为您调用该方法的编译时类型。在本例中,它是从
Foo.Something
中调用/解析的,
this
的编译时类型是
Foo
,而不是
Bar

一个选项是使调用
虚拟
,并让每种类型的
覆盖它。这将使每次调用方法时都提供编译时类型信息:

public class Foo
{
    public virtual void DoSomething()
    {
        DoSomething(this);
    }

    //notice this is protected now so it's accessible to `Bar`
    protected static void DoSomething<T>(T obj)
    {
        var generic = new Generic<T>();
    }
}

public class Bar : Foo
{
    public override void DoSomething()
    {
        DoSomething(this);
    }
}
公共类Foo
{
公共虚拟空间DoSomething()
{
DoSomething(这个);
}
//请注意,现在它已被保护,因此可以访问'Bar'`
受保护静态空隙剂量测量(T obj)
{
var generic=new generic();
}
}
公共类酒吧:富
{
公共覆盖无效DoSomething()
{
DoSomething(这个);
}
}
另一个选项是使用动态语言运行时在运行时解析类型:

public class Foo
{
    public void DoSomething()
    {
        dynamic thisDynamic = this;
        DoSomething(thisDynamic);
    }

    private static void DoSomething<T>(T obj)
    {
        var generic = new Generic<T>();
    }
}
公共类Foo
{
公共无效剂量测定法()
{
动态这个动态=这个;
剂量测定法(thisDynamic);
}
专用静态空隙剂量仪(T obj)
{
var generic=new generic();
}
}
编辑:如果您未使用.NET 4.0,并且没有访问动态语言运行时的权限,则也可以使用泛型:

public class Foo
{
    public void DoSomething()
    {
        DoSomething(this);
    }

    private static void DoSomething(object obj)
    {
        Type runtimeType = obj.GetType();
        MethodInfo createMethod = typeof(Foo).GetMethod("CreateGeneric", BindingFlags.Static | BindingFlags.NonPublic);
        var genericCreateMethod = createMethod.MakeGenericMethod(runtimeType);
        genericCreateMethod.Invoke(null, new[]{obj});
    }

    private static void CreateGeneric<T>(T obj)
    {
        var generic = new Generic<T>();
    }
}
公共类Foo
{
公共无效剂量测定法()
{
DoSomething(这个);
}
私有静态无效剂量测量(对象obj)
{
类型runtimeType=obj.GetType();
MethodInfo createMethod=typeof(Foo).GetMethod(“CreateGeneric”,BindingFlags.Static | BindingFlags.NonPublic);
var genericCreateMethod=createMethod.MakeGenericMethod(runtimeType);
Invoke(null,new[]{obj});
}
专用静态void CreateGeneric(T obj)
{
var generic=new generic();
}
}

注意,我假设您需要
CreateGeneric
方法中的
tobj
参数。如果您实际上不需要它,您可以更新方法签名并调用反射代码来忽略它。

@PatrickHofman-编译器可以从调用中推断泛型参数是
Foo
。谢谢,这是最简单的解决方案!谢谢你详细的回答。我使用了Jon提出的解决方案,这是最容易实现的。