it-swarm-pt.tech

Método genérico em que T é type1 ou type2

Existe uma maneira de declarar uma função genérica que o tipo genérico é de type1 ou type2?

exemplo:

public void Foo<T>(T number)
{
}

Posso restringir T a ser int ou longo

23
gdoron

Embora você possa usar uma restrição generic para limitar o tipo de cada argumento genérico T, infelizmente não há nenhum que permita impor em tempo de compilação se T é type1 or type2.

Também não há nenhuma maneira de impor em tempo de compilação que seu argumento genérico possa ser de qualquer tipo primitivo (int, long, double, ...).

14
Darin Dimitrov

Para objetos ReferenceType, você pode fazer

public void DoIt<T>(T someParameter) where T : IMyType
{

}

...

public interface IMyType
{
}

public class Type1 : IMyType
{
}

public class Type2 : IMyType
{
}

Para o seu caso, usando long como parâmetro irá restringir o uso para longs e ints de qualquer maneira.

public void DoIt(long someParameter)
{

}

para restringir a qualquer tipo de valor (como: int, double, short, decimal) você pode usar:

public void DoIt<T>(T someParameter) where T : struct
{

}

para mais informações você pode conferir a documentação oficial aqui

14
Adam Moszczyński

Não.

Isso não faz sentido; T não teria nenhum tipo de tempo de compilação utilizável no método.

Em vez disso, você deve fazer dois métodos sobrecarregados.

7
SLaks

Use métodos sobrecarregados:

public void Foo(int number)
{
} 

public void Foo(long number)
{
}

Você não pode executar operações aritméticas em tipos genéricos de qualquer maneira. Observe que você pode passar um valor int para um parâmetro long. Ele será convertido automaticamente para long. Ter apenas um único método com um parâmetro long poderia ser suficiente.

Linguagens de programação antigas funcionavam após o princípio "Pode haver apenas um". C # permite que você tenha vários métodos com o mesmo nome na mesma classe, interface ou struct. Esses métodos devem ter uma assinatura diferente. Isso significa que eles devem ter um número diferente de parâmetros ou parâmetros com tipos diferentes (ou ambos). Isso é chamado sobrecarga de método.

5
Olivier Jacot-Descombes

Eu sei que esta é uma questão antiga, e isso não responde perfeitamente, mas você pode fazer isso com um único método, ao invés de criar múltiplos, ou usando restrições genéricas ... especialmente útil se você tem 20 tipos ímpares para verificar.

Obviamente, você não obtém a verificação do tipo de compilador como faz ao usar uma restrição, mas isso pode ajudar em certas circunstâncias ...

public void MyMethod<T>()
{
    if (!typeof(T).Equals(typeof(int)) &&
        !typeof(T).Equals(typeof(long)))
            throw new Exception("T must be int or long");

    //your logic here
}
0
Detail

Eu não acho que isso seja possível no momento.

Esta questão sobre a criação de uma biblioteca de matemática abrange o mesmo terreno e inclui alguns trabalhos em torno.

0
Jon Egerton

Eu também tive esse problema e acho que encontrei uma solução melhor (supondo que uma versão sobrecarregada do seu método é insuficiente):

Misturar Type1 e Type2 sem nenhum paralelismo não faz sentido, como já foi escrito. Portanto, deve haver qualquer método ou propriedade acessada para os dois tipos de objetos. Para garantir ao compilador que esses métodos ou propriedades estão disponíveis para o seu objeto, agrupe Type1 e Type2 criando uma interface MyInterface e implementando-a por Type1 e Type2:

interface MyInterface {
  void MyCommonMethod();
  bool MyCommonProperty { get; }
}

class Type1 : MyInterface {
  void MyCommonMethod() {
    // TODO: Implement it for Type1
  }

  bool MyCommonProperty {
  get {
    // TODO: Implement it for Type1
  }
  }
}

class Type2 : MyInterface {
  void MyCommonMethod() {
    // TODO: Implement it for Type2
  }

  bool MyCommonProperty {
  get {
    // TODO: Implement it for Type2
  }
  }
}

Agora, para reescrever seu método Foo para aceitar Type1 e Type2, constraint T para ser um objeto MyInterface:

public void Foo<T>(T number) where T : MyInterface
{
  throw new NotImplementedException();
}

Eu lamento isso pode ser útil. :)

0
KnorxThieus