17

我有一个类似于工厂的对象的方法。你给它一个类型,它创建一个实例并做一些其他的事情。一种优雅的方式(在我看来)是这样的:

public T MagicMethod<T>() where T: SomeBaseClass
{
    // Magic goes here
}

但这让 FxCop 感到不安,他说这是一种糟糕的风格 - 我收到“CA1004:通用方法应提供类型参数”警告。关于不使用推理和东西的东西。所以,我能想到的唯一其他方法是这样的:

public SomeBaseClass MagicMethod(Type T)
{
    // Same magic goes here
}

我相信这在许多帐户上不如第一种方法,但是样式规则...有关警告的MSDN文章甚至说没有理由压制它。

毕竟,我通过压制这个警告做得对吗?

4

7 回答 7

18

我相信您误解了 FxCop 告诉您的内容,可能是因为它的措辞不够理想。这意味着泛型方法应该提供该类型Type的参数,而不是泛型方法应该具有提供运行时实例的非泛型重载。例如,

public void DoSomething<T>(T myParam);

myParam是它所指的参数类型。正如您所建议的,它想要这样做的原因是为了推断。这使您可以执行类似...

string foo = "bar";

DoSomething(foo);

而不必写

DoSomething<string>(foo);

在您的情况下,可以抑制警告,因为您希望用户明确指定类型。但是,我建议(假设您的构造函数是无参数的)您将您更改wherewhere T : SomeBaseClass, new(). 这意味着它将指示编译器要求传入的任何类型都具有无参数构造函数。这也意味着你可以new T()在你的代码中做。

于 2009-07-31T12:16:01.567 回答
5

我不会有抑制这个警告的问题。对于初学者来说,MS自己的代码中的等价物是Activator.CreateInstance<T>()

public static T CreateInstance<T>()

这意味着分析规则应该考虑方法的返回类型是否被泛型参数覆盖......

之前很多地方都提到过:

规则中有以前的错误,例如:

public static void GenericMethod<T>(List<T> arg);

以前会触发它(在 2005 SP1 中修复)。

我建议为您的具体示例提交一个连接错误

于 2009-07-31T12:36:30.530 回答
2

FXCop 警告就是这样 - 警告。就像隐式强制转换警告一样,它们可以让你知道你正在做的事情可能有你没有预料到的行为,或者可能不是你想要的。

通过查看代码来处理隐式转换警告,确定您是否确实打算这样做,如果是,则添加显式转换。

与 FXCop 相同。查看警告,查看您的代码,并确定警告是否有效。如果是,请修复它。如果没有,请压制它。抑制等同于显式演员 - “是的,FXCop,我确定我想这样做。”

如果它真的是一个错误,那可能是一个编译器错误。

于 2009-08-01T04:47:14.627 回答
1

即使您在一个或多个参数中使用了泛型类型参数,如果它没有“剥离”,FxCop 也会触发该警告:

public void LinkedList<T> Slice<T>(LinkedList<T> collection, Predicate<T> match)
{
    ...
}

至少规则“CA1004”前几天在具有此签名的方法上“错误地”触发。

由于比 FxCop 团队更聪明,我不确定规则是否能够在所有情况下正确确定代码,这就是置信度的用途:)

于 2009-08-01T10:14:55.120 回答
0

第二种方法甚至不等同于第一种。在第二个中,您实际上被赋予了一个类型,但您不能实例化该类型的对象(除非您使用反射 --- eeek!)并且您必须显式声明返回类型(这违背了泛型的目的首先)。

请参阅有关抑制它的说明看来压制也无妨。

编辑:现在这是另一个想法。如果您将其更改为“out”参数并且没有通过返回变量返回它会怎样?那么它会删除警告吗?

public void MagicMethod<T>( out T retVar ) where T: SomeBaseClass
{
    // Magic goes here
}
于 2009-07-31T12:11:10.227 回答
0

就我个人而言,我会为 Fxcop 中的大多数警告而烦恼。

您似乎知道自己在做什么,为什么某些自动化软件会更清楚?

好吧,它不能,这是一个猜测。

于 2009-07-31T12:12:05.873 回答
0

首先,该警告只是为了确保调用者在知情的情况下做所有事情。可以在不传递任何类型参数的情况下调用您的方法,因为编译器事先知道对象的类型。FxCop 告诉你让它是隐式的,这样使用泛型和非泛型重载的语法看起来是相同的(我不同意这个原则,但这是个人的,在这里不相关)。

其次,你的第二种方法会造成比你现在想象的更多的伤害。那里没有编译时类型检查,因此如果您使用它,请注意运行时无效转换异常。

于 2009-08-01T10:07:22.563 回答