How to pass a type to a method - Type argument vs generics

Vilx- picture Vilx- · Jul 31, 2009 · Viewed 10k times · Source

I have a method of an object which is something like a factory. You give it a type, it creates an instance and does a few other things. An elegant way to do it (in my opinion) is like this:

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

But this upsets FxCop who says that this is a bad style - I get a "CA1004: Generic methods should provide type parameter" warning. Something about not being to use inference and stuff. So, the only other way I can think of is something like this:

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

I believe this is inferior to the first method on many accounts, but the style rule... The MSDN article on the warning even says that there is no reason for suppressing it.

Am I doing it right by suppressing this warning after all?

Answer

Adam Robinson picture Adam Robinson · Jul 31, 2009

I believe you're misunderstanding what FxCop is telling you, probably because its wording is less than ideal. What it means is that a generic method should provide a parameter that is of that type, not that a generic method should have a non-generic overload that provides a runtime Type instance. For example,

public void DoSomething<T>(T myParam);

The myParam is the sort of parameter it's referring to. The reason it wants this is, as you suggest, for inference. This allows you to do something like...

string foo = "bar";

DoSomething(foo);

instead of having to write

DoSomething<string>(foo);

In your case, it's fine to suppress the warning since you want the user to explicitly specify the type. I would suggest, however (assuming that your constructors are parameterless) that you change your where to where T : SomeBaseClass, new(). This means that it will direct the compiler to require that whatever type is passed in have a parameterless constructor. This also means that you can do new T() in your code.