想要 return 与不使用对象的单个泛型方法调用不同 类

Would like to return different classes from a single generic method call without using object

我有三个classes——非常简单的例子:

    public class MyTableLayoutPanelBase : TableLayoutPanel
    {
    }

    public class MyTableLayoutPanelExt : MyTableLayoutPanelBase
    {
    }

    public class MyTableLayoutPanelUltraExt : MyTableLayoutPanelExt
    {
    }

Base subclass subclass是 Microsoft WinForms TableLayoutPanel 控件。然后我有一个 Ext 版本进一步子classes 我的 Base class 和一个 UltraExt 子classes Ext class。在我的实际使用中,Base、Ext 和 UltraExt subclasses 添加了一些超出继承的属性。为了便于讨论,所有这些 class 都具有相同的实现...

我想要的是 return 这些子classed 对象之一的工厂。我采取的方法是这样做的:

    public static object CreateMyTableLayoutPanelControl<T>() 
    {
        if (typeof(T) == typeof(MyTableLayoutPanelControlBase))
        {
            return new MyTableLayoutPanelControlBase();
        }
        if (typeof(T) == typeof(MyTableLayoutPanelControlExt))
        {
            return new MyTableLayoutPanelControlExt();
        }
        if (typeof(T) == typeof(MyTableLayoutPanelControlUltraExt))
        {
            return new MyTableLayoutPanelControlUltraExt();
        }
    }

这让我可以做这样的事情:

var myTableLayoutPanelControlExt = (MyTableLayoutPanelExt)CreateMyTableLayoutPanelControl<MyTableLayoutPanelExt>();

问题是我需要将对象 returned 转换为我需要的子 class 类型——我知道只要我转换为三个类型之一,转换就会成功我知道 CreateMyTableLayoutPanelControl 类型 return。但那很笨拙,而且很昂贵。我更愿意从工厂收到我需要的正确类型的实际对象。

有没有一种方法可以利用泛型以及我的 classes 没有实现接口 return 不是对象而是请求的实际 class 实例的事实CreateMyTableLayoutControl 泛型调用?理想情况下,我希望此代码无需转换即可工作:

MyTableLayoutPanelExt myTableLayoutPanelControlExt = CreateMyTableLayoutPanelControl<MyTableLayoutPanelExt>();

您可以分两步完成:

首先,使用 Type 参数创建一个 non-generic 方法来完成繁重的工作:

public static MyTableLayoutPanelBase CreateMyTableLayoutPanelControl(Type t)
{
    if (t == typeof(MyTableLayoutPanelBase))
    {
        return new MyTableLayoutPanelBase();
    }
    if (t == typeof(MyTableLayoutPanelExt))
    {
        return new MyTableLayoutPanelExt();
    }
    if (t == typeof(MyTableLayoutPanelUltraExt))
    {
        return new MyTableLayoutPanelUltraExt();
    }
    return null;
}

然后,您可以轻松地提供一个通用版本为您进行转换:

public static T CreateMyTableLayoutPanelControl<T>() where T : MyTableLayoutPanelBase
{
    return (T)CreateMyTableLayoutPanelControl(typeof(T));
}

您可以尝试将 Activator.CreateInstance 函数与泛型一起使用,然后让泛型类型与您的基础类型 TableLayoutPanel 建立契约 TableLayoutPanel

public static T CreateMyTableLayoutPanelControl<T>() 
    where T : TableLayoutPanel
{
    return Activator.CreateInstance<T>();
}

I would not return object type from the method unless necessary, because it will cause some problems.

c# fiddle