Quero escrever uma função que pode validar um determinado valor (passado como uma string) em relação aos valores possíveis de um enum
. No caso de uma correspondência, ele deve retornar a instância de enum; caso contrário, ele deve retornar um valor padrão.
A função não pode usar try
/ internamente catch
, o que exclui o uso Enum.Parse
, que lança uma exceção quando fornecido um argumento inválido.
Eu gostaria de usar algo semelhante a uma TryParse
função para implementar isso:
public static TEnum ToEnum<TEnum>(this string strEnumValue, TEnum defaultValue)
{
object enumValue;
if (!TryParse (typeof (TEnum), strEnumValue, out enumValue))
{
return defaultValue;
}
return (TEnum) enumValue;
}
Respostas:
Como outros já disseram, você deve implementar o seu próprio
TryParse
. Simon Mourier está fornecendo uma implementação completa que cuida de tudo.Se você estiver usando enums de campo de bits (isto é, sinalizadores), você também terá que lidar com uma string como a
"MyEnum.Val1|MyEnum.Val2"
qual é uma combinação de dois valores de enum. Se você apenas chamarEnum.IsDefined
com esta string, ele retornará false, emboraEnum.Parse
seja correto.Atualizar
Conforme mencionado por Lisa e Christian nos comentários,
Enum.TryParse
agora está disponível para C # em .NET4 e superior.MSDN Docs
fonte
Enum.IsDefined fará as coisas. Pode não ser tão eficiente quanto um TryParse provavelmente seria, mas funcionará sem tratamento de exceção.
Vale a pena notar: um
TryParse
método foi adicionado no .NET 4.0.fonte
GetNames
. Internamente, todos esses métodos (incluindoParse
) usamGetHashEntry
, que faz a reflexão real - uma vez. O lado bom é que o .NET 4.0 tem um TryParse e é genérico também :)Aqui está uma implementação personalizada de
EnumTryParse
. Ao contrário de outras implementações comuns, ele também suporta enum marcado com oFlags
atributo.fonte
Activator.CreateInstance(type)
para criar o valor enum padrão e nãoEnum.ToObject(type, 0)
. É só uma questão de gosto?No final, você deve implementar isso em torno de
Enum.GetNames
:Notas Adicionais:
Enum.TryParse
está incluído no .NET 4. Veja aqui http://msdn.microsoft.com/library/dd991876(VS.100).aspxEnum.Parse
captura da exceção lançada quando ela falha. Isso pode ser mais rápido quando uma correspondência é encontrada, mas provavelmente será mais lento se não for. Dependendo dos dados que você está processando, isso pode ou não ser uma melhoria líquida.EDIT: Acabei de ver uma implementação melhor sobre isso, que armazena em cache as informações necessárias: http://damieng.com/blog/2010/10/17/enums-better-syntax-improved-performance-and-tryparse-in-net- 3-5
fonte
Flags
atributo.Baseado em .NET 4.5
Amostra de código abaixo
Referência: http://www.dotnetperls.com/enum-parse
fonte
Eu tenho uma implementação otimizada que você pode usar no UnconstrainedMelody . Efetivamente, ele está apenas armazenando em cache a lista de nomes, mas está fazendo isso de uma forma agradável, fortemente tipada e genericamente restrita :)
fonte
...
fonte
Atualmente não há Enum.ExperimenteParse pronto para uso. Isso foi solicitado no Connect ( Still no Enum.TryParse ) e obteve uma resposta indicando possível inclusão na próxima estrutura após .NET 3.5. Você terá que implementar as soluções alternativas sugeridas por enquanto.
fonte
A única maneira de evitar o tratamento de exceções é usar o método GetNames (), e todos sabemos que as exceções não devem ser abusadas para a lógica de aplicativo comum :)
fonte
O armazenamento em cache de uma função / dicionário gerado dinamicamente é permitido?
Como você (parece) não sabe o tipo de enum com antecedência, a primeira execução pode gerar algo de que as execuções subsequentes podem tirar proveito.
Você pode até armazenar em cache o resultado de Enum.GetNames ()
Você está tentando otimizar para CPU ou memória? Você realmente precisa?
fonte
Como outros já disseram, se você não usa Try & Catch, você precisa usar IsDefined ou GetNames ... Aqui estão alguns exemplos ... eles são basicamente todos iguais, o primeiro lidando com enums anuláveis. Eu prefiro o segundo porque é uma extensão das cordas, não enums ... mas você pode mixá-los como quiser!
fonte
Não há um TryParse porque o tipo do Enum não é conhecido até o tempo de execução. Um TryParse que segue a mesma metodologia, digamos, do método Date.ExperimenteParse lançaria um erro de conversão implícito no parâmetro ByRef.
Eu sugiro fazer algo assim:
fonte
Try
métodos cujos resultados podem ser tipos de valor, ou ondenull
pode ser um resultado legítimo (por exemplo,Dictionary.TryGetValue, which has both such traits), the normal pattern is for a
método Try` para retornarbool
e passar o resultado como umout
parâmetro. Para aqueles que retornam tipos de classe ondenull
não é um resultado válido, não há dificuldade em usar umnull
retorno para indicar falha.Dê uma olhada na própria classe Enum (struct?). Existe um método Parse nisso, mas não tenho certeza sobre um tryparse.
fonte
Este método converterá um tipo de enum:
Ele verifica o tipo subjacente e obtém o nome dele para analisar. Se tudo falhar, ele retornará o valor padrão.
fonte