Estou usando a reflexão para percorrer Type
as propriedades de a e definir certos tipos como padrão. Agora, eu poderia mudar o tipo e definir default(Type)
explicitamente, mas prefiro fazê-lo em uma linha. Existe um equivalente programático do padrão?
c#
reflection
default
tags2k
fonte
fonte
Respostas:
Na versão mais recente do .net, como o padrão .net,
type.IsValueType
precisa ser escrita comotype.GetTypeInfo().IsValueType
fonte
default(T) != (T)(object)default(T) && !(default(T) != default(T))
com argumento, caso contrário, não importa se está em caixa ou não, pois são equivalentes.default(T) != default(T)
retorno falso, e isso é trapaça! =)Array.CreateInstance(type, length)
.Por que não chamar o método que retorna o padrão (T) com reflexão? Você pode usar GetDefault de qualquer tipo com:
fonte
nameof(GetDefaultGeneric)
se puder, em vez de"GetDefaultGeneric"
Você pode usar
PropertyInfo.SetValue(obj, null)
. Se chamado em um tipo de valor, ele fornecerá o padrão. Esse comportamento está documentado no .NET 4.0 e no .NET 4.5 .fonte
Se você estiver usando o .NET 4.0 ou superior e desejar uma versão programática que não seja uma codificação de regras definidas fora do código , poderá criar um
Expression
, compilar e executá-lo rapidamente.O seguinte método de extensão utilizará ae
Type
obterá o valor retornadodefault(T)
peloDefault
método naExpression
classe:Você também deve armazenar em cache o valor acima com base em
Type
, mas esteja ciente de que, se você está chamando isso para um grande número deType
instâncias, e não o usa constantemente, a memória consumida pelo cache pode superar os benefícios.fonte
e.Compile()
. Esse é o objetivo das expressões.e.Compile()
deve ser armazenado em cache, mas supondo que esse método seja aproximadamente 14x mais rápido, por exemplolong
. Consulte gist.github.com/pvginkel/fed5c8512b9dfefc2870c6853bbfbf8b para obter o benchmark e os resultados.e.Compile()
em cache e nãoe.Compile()()
? ou seja, o tipo padrão de um tipo pode ser alterado em tempo de execução? Caso contrário (como acredito que seja o caso), você pode simplesmente armazenar em cache o resultado, em vez da expressão compilada, o que deve melhorar ainda mais o desempenho.Por que você diz que os genéricos estão fora de cena?
fonte
Esta é a solução otimizada da Flem:
fonte
return type.IsValueType ? typeDefaults.GetOrAdd(type, Activator.CreateInstance) : null;
A resposta escolhida é uma boa resposta, mas tenha cuidado com o objeto retornado.
Extrapolando ...
fonte
As expressões podem ajudar aqui:
Não testei esse trecho, mas acho que ele deve produzir nulos "digitados" para tipos de referência.
fonte
"typed" nulls
- explicar. Que objeto você está retornando? Se você retornar um objeto do tipotype
, mas seu valor fornull
, ele não poderá - não poderá - ter nenhuma outra informação além dessanull
. Você não pode consultar umnull
valor e descobrir que tipo ele supostamente é. Se você NÃO retornar nulo, mas retornar .. Eu não sei o que .., então não funcionará comonull
.Ainda não consigo encontrar nada simples e elegante, mas tenho uma ideia: se você conhece o tipo de propriedade que deseja definir, pode escrever sua própria
default(T)
. Existem dois casos -T
é um tipo de valor eT
é um tipo de referência. Você pode ver isso verificandoT.IsValueType
. SeT
é um tipo de referência, você pode simplesmente configurá-lo paranull
. SeT
for um tipo de valor, ele terá um construtor sem parâmetros padrão que você pode chamar para obter um valor "em branco".fonte
Eu faço a mesma tarefa assim.
fonte
Equivalente à resposta de Dror, mas como método de extensão:
fonte
Pequenos ajustes na solução do @Rob Fonseca-Ensor : O método de extensão a seguir também funciona no .Net Standard desde que eu uso GetRuntimeMethod em vez de GetMethod.
... e o teste de unidade correspondente para aqueles que se preocupam com a qualidade:
fonte
fonte
Nullable<T>
tipos: não retorna o equivalente aodefault(Nullable<T>)
que deveria sernull
. A resposta aceita pelo Dror funciona melhor.Isso deve funcionar:
Nullable<T> a = new Nullable<T>().GetValueOrDefault();
fonte