1

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

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

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

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

有没有办法完成我在 C# 中尝试做的事情?

4

5 回答 5

4

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

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

T test = Factory < T >.Create(... some vars ...);

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

在这里查看讨论

于 2012-08-01T16:07:20.997 回答
2

这应该是你所追求的:

class MyFactory<T> where T : new()
{
    public T CreateMyStuff()
    {
        return new T();
    }
}
于 2012-08-01T16:06:37.890 回答
0

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

您不能针对泛型参数调用静态方法。IE:你不能在T.

于 2012-08-01T16:01:47.240 回答
0

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

T 是一个类型,而不是变量,所以除非 Create() 方法是该类型的静态方法,否则它不会编译,即使这样 T 也不知道 create 实际上是什么,所以你将无法编译函数调用开始。如果您以某种方式约束 T 以便代码知道 Create() 函数存在,那么您可以这样做。

例子

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

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

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

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

于 2012-08-01T16:08:02.297 回答
0

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

// 假设你需要能够创建构造函数应该采用的东西
// 一个 Int32。然后执行以下操作:

void MakeLotsOfTs<T>(Func<Int32, T> CreationProc) // 以及你想要的任何其他东西
{
  ...每当您需要给定整数 N 的新 T 时,请调用 CreationProc(N)
}

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

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

请注意,即使您想将其与构造函数需要其他内容的类一起使用,这种方法也可以使用(例如,可以执行以下操作:

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

与指定“参数化”约束相比,这种方法需要为调用者做更多的工作new,但功能更强大。

于 2012-08-01T16:53:08.630 回答