繁体   English   中英

使用C#泛型从方法(不是“新”)创建泛型对象

[英]Using C# Generics to create a generic object from a method (not “new”)

我习惯了C ++模板,并意识到在C#中工作原理有些不同。 这就是我想要的:

    T CreateButton<T>() {
       T test = T.create(...some vars...);
       return test;
    }

我以为也许在定义了“创建”方法的基类中使用派生约束可以解决问题,但仍然无法编译。

我收到此编译错误: **error CS0119: Expression denotes a 'type parameter', where a 'variable', 'value' or 'type' was expected**

有没有一种方法可以完成我在C#中要做的事情?

您的问题是您正在调用T.Create,就好像它是通用T上的静态方法一样。这带来了两个问题-首先,您无法继承静态变量(必须这样做才能将T的类型限制为定义“静态创建”的基本类,以便T.Create进行编译)。 其次,即使您可以继承静态方法,基类.Create()也必须以某种方式“知道”返回T。

您在这里追求的是一家工厂。 定义一个充当T工厂的类,然后您可以编写

T test = Factory <T> .Create(...一些变量...);

感觉这会导致巨大的switch语句-基于T的真实类型做正确的事情。 但这是控制反转和依赖注入可以为您提供帮助的地方。 为您需要的每种T类型定义一个带有“插件”的工厂。 使用IoC将插件注入您的工厂。

这里查看讨论

这应该是您所追求的:

class MyFactory<T> where T : new()
{
    public T CreateMyStuff()
    {
        return new T();
    }
}

您必须定义和实现接口(或基类)。 您还必须约束new() 然后,您可以对其使用通用约束。

您不能针对通用参数调用静态方法。 IE:您无法在T上调用静态方法。

问题在于特定行T.Create(...)

T是一个Type,而不是变量,因此,除非Create()方法是该类型的静态方法,否则它将无法编译,即使T也不知道create的真正含义,因此您将无法编译函数调用从此开始。 如果以某种方式约束T,以使代码知道存在Create()函数,则可以执行此操作。

假设T将始终是某个Base类的成员或继承的成员,则该函数将声明如下:

T CreateButton<T>() where T : BusinessObjectBase
{
   T test = (T)BusinessObjectBase.create(...some vars...);
   return test;
}

在这种情况下,静态函数Create()在BusinessObjectBase内部声明,并且作为T传入的类型被约束为该类或从该类扩展,从而保证T能够调用Create()的代码。功能。

当然,正如其他人提到的那样,使用new()约束要容易得多。 这使您可以简单地返回新的T();。 复杂程度要低得多,但是您会丢失create函数中的那些参数。

除了满足new约束的类型外,没有任何方法可以创建泛型的新对象,仅提供类型即可。 相反,最好的选择可能是让需要创建事物的方法接受适合该任务的委托。

// Suppose you need to be able to create things whose constructors should take
//  an Int32.  Then do something like:

void MakeLotsOfTs<T>(Func<Int32, T> CreationProc) // And whatever other stuff you want
{
  ... whenever you need a new T for a given integer N, call CreationProc(N)
}

如果您有一个Foo类,其构造函数使用Int32 ,并且希望将其传递给上述方法,请使用

  MakeLotsOfTs<Foo>( (Int32 param) => new Foo(param) );

Note that this approach will work even if you want to use it with a class whose constructor requires something else (e.g. one could do something like:

MakeLotsOfTs<Bar>( (Int32 param) => new Bar(String.Format("Bar #{0}", param)) );

与能够指定“参数化” new约束相比,此方法对调用者的工作量更多,但是功能更强大。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM