Eu tenho uma classe Animal
e sua subclasse Dog
. Costumo encontrar-me codificando as seguintes linhas:
if (animal is Dog)
{
Dog dog = animal as Dog;
dog.Name;
...
}
Para a variável Animal animal;
.
Existe alguma sintaxe que me permite escrever algo como:
if (Dog dog = animal as Dog)
{
dog.Name;
...
}
c#
casting
if-statement
Michael
fonte
fonte
bool
condição?null
,! =false
Em C #; O C # permite apenas bools reais ou coisas implicitamente conversíveis em bools emif
condições. Nulos nem nenhum dos tipos inteiros são implicitamente convertíveis em bools.Respostas:
A resposta abaixo foi escrita anos atrás e atualizada ao longo do tempo. No C # 7, você pode usar a correspondência de padrões:
Observe que
dog
ainda está no escopo após aif
instrução, mas não está definitivamente atribuído.Não, não existe. É mais idiomático escrever isso:
Dado que "como seguido de se" é quase sempre usado dessa maneira, pode fazer mais sentido haver um operador que execute as duas partes de uma só vez. No momento, isso não está no C # 6, mas pode fazer parte do C # 7, se a proposta de correspondência de padrões for implementada.
O problema é que você não pode declarar uma variável na parte da condição de uma
if
instrução 1 . A abordagem mais próxima que consigo pensar é a seguinte:Isso é desagradável ... (Eu apenas tentei, e funciona. Mas, por favor, não faça isso. Ah, e você pode declarar
dog
usando, évar
claro).Claro que você pode escrever um método de extensão:
Em seguida, chame-o com:
Como alternativa, você pode combinar os dois:
Você também pode usar um método de extensão sem uma expressão lambda de maneira mais limpa que o loop for:
Então:
1 Você pode atribuir valores em
if
declarações, embora raramente o faça. Isso não é o mesmo que declarar variáveis. Não é muito incomum para mim fazê-lo de uma vezwhile
ao ler fluxos de dados. Por exemplo:Hoje em dia, normalmente prefiro usar um invólucro que me permita usar,
foreach (string line in ...)
mas vejo o acima como um padrão bastante idiomático. É geralmente não bom ter efeitos colaterais dentro de uma condição, mas as alternativas geralmente envolvem a duplicação de código, e quando você sabe que este padrão é fácil de acertar.fonte
EVIL EVIL EVIL
, mas não sou positivo.AsEither(...)
, acho que é um pouco mais claro do queAsIf(...)
, para que eu possa escrevermyAnimal.AsEither(dog => dog.Woof(), cat => cat.Meeow(), unicorn => unicorn.ShitRainbows())
.Se
as
falhar, ele retornaránull
.fonte
if
declaração e não no escopo externo.if
pode ter um resultado booleano e uma atribuição.Dog dog; if ((dog = animal as Dog) != null) { // Use Dog }
mas isso ainda introduz a variável no escopo externo.Você pode atribuir o valor à variável, desde que a variável já exista. Você também pode definir o escopo da variável para permitir que o nome da variável seja usado novamente mais tarde no mesmo método, se houver algum problema.
assumindo
obtém saída:
O padrão de atribuição de variável no teste também é usado ao ler blocos de bytes de fluxos, por exemplo:
O padrão de escopo da variável usado acima, no entanto, não é um padrão de código particularmente comum e, se eu o visse sendo usado em todo o lugar, estaria procurando uma maneira de refatorá-lo.
fonte
Provavelmente haverá no C # 6.0. Esse recurso é chamado de "expressões de declaração". Vejo
https://roslyn.codeplex.com/discussions/565640
para detalhes.
A sintaxe proposta é:
De maneira mais geral, o recurso proposto é que uma declaração de variável local possa ser usada como expressão . Essa
if
sintaxe é apenas uma boa consequência do recurso mais geral.fonte
Try*
(por exemplo,TryParse
). Esse recurso não apenas faz essas chamadas em uma única expressão (como deveriam ser, IMO), mas também permite um escopo mais limpo dessas variáveis. Estou entusiasmado por ter oout
parâmetro de umTry
método com escopo condicional; isso dificulta a introdução de certos tipos de bugs.Um dos métodos de extensão que me vejo escrevendo e usando frequentemente * é
O que poderia ser usado nessa situação como
E então
name
é o nome do cachorro (se for um cachorro), caso contrário nulo.* Eu não tenho idéia se isso é de alto desempenho. Nunca surgiu como um gargalo na criação de perfil.
fonte
Indo contra a corrente aqui, mas talvez você esteja fazendo errado em primeiro lugar. Verificar o tipo de objeto é quase sempre um cheiro de código. Todos os animais, no seu exemplo, não têm um nome? Em seguida, basta chamar Animal.name, sem verificar se é um cachorro ou não.
Como alternativa, inverta o método para chamar um método em Animal que faça algo diferente, dependendo do tipo concreto do animal. Veja também: Polimorfismo.
fonte
Declaração mais curta
fonte
Aqui estão alguns códigos sujos adicionais (embora não tão sujos quanto os de Jon :-)) dependentes da modificação da classe base. Eu acho que captura a intenção, embora talvez não entenda:
fonte
Se você precisar fazer vários como-se um após um (e usar polimorfismo não é uma opção), considere usar uma construção SwitchOnType .
fonte
O problema (com a sintaxe) não está na atribuição, pois o operador de atribuição em C # é uma expressão válida. Pelo contrário, é com a declaração desejada, pois as declarações são declarações.
Se eu devo escrever um código assim, às vezes (dependendo do contexto maior), escrevo o código assim:
Há méritos com a sintaxe acima (que é próxima da sintaxe solicitada) porque:
dog
fora doif
resultará em um erro de compilação, pois ele não recebe um valor em outro lugar. (Ou seja, não designe paradog
outro lugar.)if/else if/...
(Existem apenas asas
necessárias para selecionar uma ramificação apropriada; esse é o grande caso em que eu a escrevo neste formulário quando necessário).is/as
. (Mas também feito comDog dog = ...
forma.)Para realmente isolar
dog
do resto do mundo, um novo bloco pode ser usado:Feliz codificação.
fonte
você pode usar algo assim
// Declarar variável bool temp = false;
fonte
Outra solução MAU com métodos de extensão :)
Pessoalmente, prefiro o jeito limpo:
fonte
Uma instrução if não permitirá isso, mas um loop for permitirá.
por exemplo
Caso a maneira como funcione não seja imediatamente óbvia, aqui está uma explicação passo a passo do processo:
iteração.
fonte
fonte
IDK, se isso ajudar alguém, mas você sempre pode tentar usar um TryParse para atribuir sua variável. Aqui está um exemplo:
A variável total seria declarada antes da sua instrução if.
fonte
Acabei de descrever a instrução if para criar uma linha de código que se parece com o que você está interessado. Isso apenas ajuda a comprimir o código e achei mais legível, especialmente ao aninhar atribuições:
fonte
Eu sei que estou super atrasada para a festa, mas achei que iria postar minha própria solução alternativa para esse dilema, já que ainda não a vi aqui (ou em qualquer outro lugar).
Com isso, você pode fazer coisas como:
NOTA IMPORTANTE: Se você deseja usar TryAs () usando uma interface, DEVE ter essa interface herdando o IAble.
Aproveitar! 🙂
fonte