Ao ler isso , aprendi que era possível permitir que um método aceitasse parâmetros de vários tipos, tornando-o um método genérico. No exemplo, o código a seguir é usado com uma restrição de tipo para garantir que "U" seja um IEnumerable<T>
.
public T DoSomething<U, T>(U arg) where U : IEnumerable<T>
{
return arg.First();
}
Encontrei um pouco mais de código que permitia adicionar várias restrições de tipo, como:
public void test<T>(string a, T arg) where T: ParentClass, ChildClass
{
//do something
}
No entanto, esse código parece impor que arg
deve ser um tipo de ParentClass
e ChildClass
. O que eu quero fazer é dizer que arg pode ser um tipo de ParentClass
ou ChildClass
da seguinte maneira:
public void test<T>(string a, T arg) where T: string OR Exception
{
//do something
}
Sua ajuda é apreciada como sempre!
c#
asp.net-mvc-3
types
Mansfield
fonte
fonte
where T : string
, comostring
é uma classe selada . A única coisa útil que você pode fazer é definir sobrecargasstring
eT : Exception
, como explicado por @ Botz3000 em sua resposta abaixo.arg
são os definidos porobject
- então, por que não remover os genéricos da imagem e fazer o tipoarg
object
? O que você está ganhando?Respostas:
Isso não é possível. No entanto, você pode definir sobrecargas para tipos específicos:
Se eles fazem parte de uma classe genérica, serão preferidos à versão genérica do método.
fonte
or
relacionamento faz com que as coisas em geral sejam úteis. Você iria ter que fazer reflexão para descobrir o que fazer e tudo isso. (QUE NOJO!).A resposta de Botz é 100% correta, aqui está uma breve explicação:
Ao escrever um método (genérico ou não) e declarar os tipos de parâmetros que o método utiliza, você define um contrato:
Se você tentar atribuir mais de um tipo por vez (com um ou) ou tentar fazer com que retorne um valor que pode ser mais de um tipo que o contrato fica confuso:
O problema é que, quando você entra no método, não tem idéia se eles lhe deram um
IJumpRope
ou umPiFactory
. Além disso, quando você segue em frente e usa o método (supondo que você o tenha compilado magicamente), você não tem certeza se possui umFisher
ou umAbstractConcreteMixer
. Basicamente, torna tudo mais confuso.A solução para o seu problema é uma das duas possibilidades:
Defina mais de um método que define cada possível transformação, comportamento ou qualquer outra coisa. Essa é a resposta de Botz. No mundo da programação, isso é conhecido como Sobrecarregando o método.
Defina uma classe base ou interface que saiba como fazer todas as coisas necessárias para o método e faça com que um método use exatamente esse tipo. Isso pode envolver agrupar uma classe
string
eException
uma classe pequena para definir como você planeja mapeá-las para a implementação, mas tudo é super claro e fácil de ler. Eu poderia vir daqui a quatro anos e ler seu código e entender facilmente o que está acontecendo.Qual você escolhe depende de quão complicada a escolha 1 e 2 seria e quão extensível ela precisa ser.
Então, para a sua situação específica, vou imaginar que você está apenas recebendo uma mensagem ou algo da exceção:
Agora, tudo o que você precisa são métodos que transformam um
string
e umException
em um IHasMessage. Muito fácil.fonte
Se ChildClass significa que é derivado de ParentClass, você pode apenas escrever o seguinte para aceitar ParentClass e ChildClass;
Por outro lado, se você quiser usar dois tipos diferentes sem nenhuma relação de herança entre eles, considere os tipos que implementam a mesma interface;
então você pode escrever sua função genérica como;
fonte
Por mais antiga que seja essa pergunta, ainda recebo votos aleatórios na minha explicação acima. A explicação ainda está perfeitamente bem, mas vou responder uma segunda vez com um tipo que me serviu bem como substituto para tipos de união (a resposta fortemente tipada para a pergunta que não é diretamente suportada pelo C #, como é )
A classe acima representa um tipo que pode ser quer TP ou TA. Você pode usá-lo como tal (os tipos se referem à minha resposta original):
Anotações importantes:
IsPrimary
primeiro.IsNeither
IsPrimary
ouIsAlternate
.Primary
eAlternate
Either
qualquer lugar em que seja esperado. Se você fazer passar umEither
onde umTA
ouTP
é esperado, mas oEither
contém o tipo errado de valor que você vai receber um erro de execução.Normalmente, uso isso onde quero que um método retorne um resultado ou um erro. Realmente limpa esse código de estilo. Eu também muito ocasionalmente ( raramente ) uso isso como um substituto para sobrecargas de método. Realisticamente, esse é um substituto muito ruim para essa sobrecarga.
fonte