2015-06-04 15 views
26

Diciamo che sto lavorando con un oggetto della classe thing. Il modo in cui sto ricevendo questo oggetto è un po 'prolisso:Questa grande cosa complicata è uguale a questo? o questo? o questo?

BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) 

vorrei vedere se questo thing è pari a x o y o z. Il modo ingenuo scrivere questo potrebbe essere:

BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == x || 
BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == y || 
BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == z 

In alcune lingue potrei scrivere qualcosa di simile:

BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == x |= y |= z 

ma C# non consente questo.

Esiste un modo C# -idiomatico per scrivere questo test come singola espressione?

+1

Si potrebbe fare qualcosa di simile a 'if (new yourtype [] {x, y, z} .Contains (BigObjectThing.Uncle.PreferredInputStream.NthRelative (5)))' –

+4

@ClaudioRedi, posta come risposta! – Joe

+1

Leggere i commenti sotto uno dovrebbe enfatizzare che '==' è probabile che (a meno che le funzioni non restituiscano realmente refs allo stesso oggetto) sia sovrascritto per fare ciò che si vuole, e sovrascrivere e usare 'Equals' sarebbe probabilmente più idiomatico. –

risposta

47

Basta usare una variabile:

var relative = BigObjectThing.Uncle.PreferredInputStream.NthRelative(5); 
return relative == x || relative == y || relative == z; 

Oppure, se si vuole ottenere fantasia con un maggior numero di cose:

var relatives = new HashSet<thing>(new[] { x, y, z }); 
return relatives.Contains(BigObjectThing.Uncle.PreferredInputStream.NthRelative(5)); 
+3

In particolare mi sto chiedendo come fare questo * come singola espressione *. – Joe

+0

Ah, mancate quello, mi dispiace. Aggiunta un'altra opzione che dovrebbe funzionare come singola espressione (supponendo che 'parenti 'sia predeterminato in precedenza) – Jacob

+2

È anche possibile incorporare' parenti' per ottenere "istruzione singola", ma è meno leggibile (talvolta utile anche nelle istruzioni LINQ concatenate). (usare semplicemente array è probabilmente sufficiente per 3 elementi - '(nuovo [] {x, y, z}). Contains ...') –

25

un metodo di estensione sarebbe simulare questo:

public static bool EqualsAny(this Thing thing, params object[] compare) 
{ 
    return compare.Contains(thing); 
} 

bool result = BigObjectThing.Uncle.PreferredInputStream.NthRelative(5).EqualsAny(x, y, z); 

C# non ha una sintassi predefinita per un simile confronto di tipo OR.

+2

potresti anche fare questo generico – aw04

+10

Ricorda che 'Contains' usa' Equals' e non '==', che è ciò che OP sta usando. Questi non sono sempre gli stessi. – Rubixus

+0

@Rubixus So per Java, è vero, ma IIRC, sono per C#. O forse sto solo pensando alle stringhe –

10

È possibile inserire prima gli oggetti in un Collection e quindi utilizzare Contains().

var relatives = new Collection<Thing> { x, y, z }; 
    if (relatives.Contains(BigObjectThing.Uncle.PreferredInputStream.NthRelative(5))) 
    { 
     ... 
    } 

Questo potrebbe essere accorciato ancora di più (al gusto di leggibilità):

if (new Collection<Thing> { x, y, z }.Contains(BigObjectThing.Uncle.PreferredInputStream.NthRelative(5))) 
{ 
    ... 
} 
14

Come altri hanno fatto notare una collezione è un modo che si possa fare questo. Se si desidera avere un po 'più di flessibilità rispetto all'utilizzo di Contains (che consente davvero di testare x.Equals(y)) e persino di supportare il concatenamento di &= in additon a |=, suggerirei i metodi di estensione Any o All incorporati in .NET.

var compares = new[] { x, y, z }; 
var relative = BigObjectThing.Uncle.PreferredInputStream.NthRelative(5); 

// Simulate |= behavior 
return compares.Any(x => relative == x); 

// Simulate &= behavior 
return compares.All(x => relative == x); 

// A more complex test chained by OR 
return compares.Any(x => relative.SomeProperty == x.SomeProperty); 

// A less readable but one-line approach 
return (new [] {x, y, x}).Any(x => BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == x); 
+1

Si noti che l'ultima opzione può eventualmente eseguire' NthRelative' volte, che dovrebbe essere evitata se l'operazione è costosa. –

+0

@ ArturoTorresSánchez Questo è un ottimo punto – mclark1129

2

fare queste cose in una sola espressione ? Questo richiede la mia abilità LINQ pazzo!

campione di lavoro (http://ideone.com/VNTFnz):

using System.Linq; 

public class Test 
{ 
    static int getStuff() 
    { 
     return 1; 
    } 

    public static void Main() 
    { 
     if ((from option in new int[] {1, 2, 3} 
       let thing = getStuff() 
       where option == thing 
       select option).Any()) 
      System.Console.WriteLine("in the list!"); 
    } 
} 

Tradotto per il vostro caso, sarebbe qualcosa di simile:

 if ((from option in new Thing[] {x, y, z} 
       let thing = BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) 
       where option == thing 
       select option).Any()) 
      System.Console.WriteLine("in the list!"); 

Non sto dicendo che si dovrebbe fare in questo modo, ma hey , ottieni il risultato booleano, puoi controllare qualsiasi numero di valori al posto di x, e z! Inoltre, questo non ti limita al confronto con ==, puoi utilizzare qualsiasi cosa ti piaccia al suo posto.

E hey, un'espressione!

Gli scherzi a parte, pensare a modi strani di fare ciò che volevi fare è divertente, ma dovresti davvero mettere il risultato di BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) in una variabile!

Problemi correlati