Usando Case / Switch e GetType para determinar o objeto [duplicado]
-
22-08-2019 - |
Pergunta
Duplicate possíveis:
C # - Existe uma melhor alternativa do que isso para 'switch no tipo'?
Se você quiser switch
em um tipo de objeto, qual é a melhor maneira de fazer isso?
Fragmento de código
private int GetNodeType(NodeDTO node)
{
switch (node.GetType())
{
case typeof(CasusNodeDTO):
return 1;
case typeof(BucketNodeDTO):
return 3;
case typeof(BranchNodeDTO):
return 0;
case typeof(LeafNodeDTO):
return 2;
default:
return -1;
}
}
Eu sei que isso não funciona dessa maneira, mas eu queria saber como você poderia resolver isso.
É um apropriado declaração if/else
neste caso?
Ou você usar a opção e adicionar .ToString()
ao tipo?
Solução
Se eu realmente teve que switch
no tipo de objeto, eu usaria .ToString()
. No entanto, gostaria de evitar a todo o custo: IDictionary<Type, int>
vai fazer muito melhor, visitante pode ser um exagero mas caso contrário, ainda é uma solução perfeitamente bem.
Outras dicas
Isto não vai resolver diretamente o seu problema que você quer mudar em seus próprios tipos definidos pelo usuário, mas para o benefício de outros que só querem ligar tipos built-in, você pode usar o TypeCode enumeração:
switch (Type.GetTypeCode(node.GetType()))
{
case TypeCode.Decimal:
// Handle Decimal
break;
case TypeCode.Int32:
// Handle Int32
break;
...
}
No blog MSDN Muitas perguntas: Interruptor do tipo é algumas informações sobre o porquê .NET não fornece ligar tipos.
Como de costume -. Soluções Alternativas sempre existe
Este não é meu, mas infelizmente eu perdi a fonte. Faz ligar tipos possíveis, mas eu pessoalmente acho que é muito estranho (a idéia dicionário é melhor):
public class Switch
{
public Switch(Object o)
{
Object = o;
}
public Object Object { get; private set; }
}
/// <summary>
/// Extensions, because otherwise casing fails on Switch==null
/// </summary>
public static class SwitchExtensions
{
public static Switch Case<T>(this Switch s, Action<T> a)
where T : class
{
return Case(s, o => true, a, false);
}
public static Switch Case<T>(this Switch s, Action<T> a,
bool fallThrough) where T : class
{
return Case(s, o => true, a, fallThrough);
}
public static Switch Case<T>(this Switch s,
Func<T, bool> c, Action<T> a) where T : class
{
return Case(s, c, a, false);
}
public static Switch Case<T>(this Switch s,
Func<T, bool> c, Action<T> a, bool fallThrough) where T : class
{
if (s == null)
{
return null;
}
T t = s.Object as T;
if (t != null)
{
if (c(t))
{
a(t);
return fallThrough ? s : null;
}
}
return s;
}
}
Uso:
new Switch(foo)
.Case<Fizz>
(action => { doingSomething = FirstMethodCall(); })
.Case<Buzz>
(action => { return false; })
Eu tinha acabado de usar uma instrução if. Nesse caso:
Type nodeType = node.GetType();
if (nodeType == typeof(CasusNodeDTO))
{
}
else ...
A outra maneira de fazer isso é:
if (node is CasusNodeDTO)
{
}
else ...
O primeiro exemplo é válido para tipos exatos somente, onde as últimas verificações de herança também.
Eu sou confrontado com o mesmo problema e me deparei com este post. É isso que se quer dizer com a abordagem IDictionary:
Dictionary<Type, int> typeDict = new Dictionary<Type, int>
{
{typeof(int),0},
{typeof(string),1},
{typeof(MyClass),2}
};
void Foo(object o)
{
switch (typeDict[o.GetType()])
{
case 0:
Print("I'm a number.");
break;
case 1:
Print("I'm a text.");
break;
case 2:
Print("I'm classy.");
break;
default:
break;
}
}
Se assim for, não posso dizer que eu sou um fã de conciliar os números no dicionário com as declarações de caso.
Este seria o ideal mas a referência dicionário mata-lo:
void FantasyFoo(object o)
{
switch (typeDict[o.GetType()])
{
case typeDict[typeof(int)]:
Print("I'm a number.");
break;
case typeDict[typeof(string)]:
Print("I'm a text.");
break;
case typeDict[typeof(MyClass)]:
Print("I'm classy.");
break;
default:
break;
}
}
Existe outra aplicação que eu tenha esquecido?
Você pode fazer isso:
if (node is CasusNodeDTO)
{
...
}
else if (node is BucketNodeDTO)
{
...
}
...
Enquanto que seria mais elegante, não é possivelmente tão eficiente quanto algumas das outras respostas aqui.
Você pode fazer isso:
function void PrintType(Type t) {
var t = true;
new Dictionary<Type, Action>{
{typeof(bool), () => Console.WriteLine("bool")},
{typeof(int), () => Console.WriteLine("int")}
}[t.GetType()]();
}
É claro e é fácil. É um pouco mais lento do que o cache do lugar dicionário .. mas para os lotes de código isso não importa de qualquer maneira ..
Uma abordagem é adicionar um método puro GetNodeType virtual () para NodeDTO e substituí-lo nos descendentes de modo que cada retornos descendentes tipo real.
Dependendo do que você está fazendo na instrução switch, a resposta correta é polimorfismo. Basta colocar uma função virtual na classe de interface / base e de substituição para cada tipo de nó.
Na verdade, eu prefiro a abordagem dada como a resposta aqui: Existe uma alternativa melhor do que isso 'switch no tipo'?
Há, porém, um bom argumento por não implementar qualquer methids de comparação de tipo em uma linguagem orientada a objeto como C #. Você poderia como alternativa estender e adicionar funcionalidades extra necessário usar a herança.
Este ponto foi discutido nos comentários dos autores do blog aqui: http: // blogs. msdn.com/b/jaredpar/archive/2008/05/16/switching-on-types.aspx#8553535
Eu encontrei este um ponto extremamente interessante, que mudou a minha abordagem em uma situação semelhante e só espero que isso ajude os outros.
Atenciosamente, Wayne