Pergunta

Eu tenho um método de um objeto que é algo como uma fábrica. Você dar-lhe um tipo, ele cria uma instância e faz algumas outras coisas. Uma maneira elegante de fazê-lo (na minha opinião) é assim:

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

Mas isso perturba FxCop que diz que este é um estilo ruim - eu recebo um "CA1004: Métodos genéricos devem fornecer o tipo de parâmetro" aviso. Algo sobre não ser usar inferência e outras coisas. Então, a única maneira que eu posso pensar é algo como isto:

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

Eu acredito que este é inferior ao primeiro método em muitas contas, mas a regra de estilo ... O artigo do MSDN sobre a advertência até diz que não há razão para suprimi-la.

Am I fazendo certo por suprimir este aviso, afinal?

Foi útil?

Solução

avisos FXCop são apenas isso - avisos. Assim como advertências conversão implícita, eles servem para que você saiba que algo que você está fazendo pode ter comportamento que você não está antecipando, ou pode não ser o que você pretende.

Um aviso conversão implícita é tratado por olhar para o código, determinining se você realmente tinha a intenção de fazer isso, e se assim for, adicionando uma conversão explícita.

A mesma coisa com FXCop. Olhe para o aviso, olhar para o seu código, e determinar se o aviso é válido. Se for, corrigi-lo. Se não, suprimi-lo. A supressão é o equivalente a uma conversão explícita - "Sim, FXCop, tenho certeza de que quer fazer isso"

Se foi realmente realmente um erro, seria provavelmente um erro do compilador.

Outras dicas

Eu acredito que você está mal-entendido que FxCop está dizendo a você, provavelmente porque a sua formulação é inferior a ideal. O que isto significa é que um método genérico deve fornecer um parâmetro que é desse tipo , não que um método genérico deve ter uma sobrecarga de não-genérico que fornece uma instância de tempo de execução Type . Por exemplo,

public void DoSomething<T>(T myParam);

O myParam é o tipo de parâmetro está se referindo. A razão que quer este é, como você sugere, por inferência. Isto permite-lhe fazer algo assim ...

string foo = "bar";

DoSomething(foo);

em vez de ter que escrever

DoSomething<string>(foo);

No seu caso, é bom para suprimir o aviso desde que você deseja que o usuário explicitamente especificar o tipo. Gostaria de sugerir, no entanto (assumindo que seus construtores são parâmetros) que você mude sua where para where T : SomeBaseClass, new(). Isso significa que ele vai dirigir o compilador para exigir que qualquer tipo é passado em ter um construtor sem parâmetros. Isto também significa que você pode fazer new T() em seu código.

Eu não teria nenhum problema com suprimir este aviso. Para começar o equivalente em próprio código de MS é Activator.CreateInstance<T>()

public static T CreateInstance<T>()

Isso implica que a regra análise deve considerar se o tipo de retorno do método é coberto pelo parâmetro genérico ...

Este tem sido mencionado em muitos lugares antes:

E tem havido erros anteriores da regra por exemplo:

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

anteriormente provocaria-la ( fixa em 2005 SP1 ).

Eu sugiro a apresentação de um erro de conexão para o seu exemplo específico

FxCop vai disparar esse aviso, mesmo se você usar o parâmetro de tipo genérico em um ou mais dos argumentos, se não for "despojado":

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

Pelo menos regra 'CA1004' despedido "em erro" aqui outro dia em um método com esta assinatura.

Para ser mais inteligente do que a equipe FxCop, eu não tenho certeza que as regras são capazes de determinar corretamente o código em todos os casos, é isso que o nível de confiança é para:)

A segunda abordagem não é ainda equivalente ao primeiro. Na segunda, você está literalmente dado um tipo, mas você não pode instanciar um objeto desse tipo (a menos que você use Reflexão --- eeek!) E você tem que declarar explicitamente o tipo de retorno (que derrota o propósito de genéricos para começar).

esta nota sobre suprimi-la. Parece que ele está bem para suprimir.

EDIT: Ora aqui está uma outra idéia. O que se mudou para um parâmetro 'out' e não devolvê-lo através da variável de retorno? Será que remover o aviso, então?

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

Pessoalmente eu gostaria de se preocupar com mais alerta em FXCop.

Você parece saber o que está fazendo, por que alguma peça automatizada de software conhecer melhor?

Bem, não posso, é um palpite.

Antes de mais nada esse aviso é apenas para se certificar de que os chamadores fazer tudo com conhecimento de causa. É possível chamar o método sem passar qualquer parâmetro de tipo, porque o compilador sabe o tipo do objeto antes da mão. FxCop está lhe dizendo para deixá-lo ser implícita para que sintaxe para utilizar sobrecargas genéricos e não genéricos parece idêntico (não concordo com esse princípio, mas que é pessoal e não é relevante aqui).

Em segundo lugar, o segundo método irá fazer mais dano do que você pode pensar agora. Não há compilação tipo tempo verificando lá, para ser avisado de exceções de tempo de execução inválido elenco se você usá-lo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top