views:

234

answers:

10

I was just working on some code and caught myself making this error

if (stringName == "firstName" || "lastName")
   // Do code

obviously this is wrong and should be

if (stringName == "firstName" || stringName == "lastName")
   // Do code

but it just got me thinking in regards to readability would the first be easier? Maybe having some logic that could say unless a new stringName is specified, use the first one?

Really not a question, Im just curious if there is something I dont fully comprehend on the logic behind compiling a statement like this.

+1  A: 

The reason they did not allow such syntax was most likely because of readability. If you're looking at the code for the first time, and you're not exactly in your best state of mind, you might not see immediately that you're comparing stringName to both "firstName" and "lastName". It just makes your intentions that much more defined.

Then again, parentheses might solve that.

nasufara
+1  A: 

That would only work if operator||(string,string) returned.. a sort of collection of strings and you had an Equals overload that took a string and that collection of strings and verified that the string is in the collection. Seems like a lot of work done behind the scenes for a very rarely used construct.

Especially since you already can do something like:

if(new string[]{"firstName","lastName"}.Contains(stringName))
    // code
Blindy
I actually think that that is less readable than before.
John Gietzen
That's a matter of taste. If you said it's wasteful, then I'd agree, it creates an array just to compare some values.
Blindy
The same technique is definitely more readable in other languages: `if stringName in ("firstName", "lastName") ...` (Python)
Greg Hewgill
+6  A: 

Having the compiler guess at the programmer's intention when the code is clearly wrong in order to fix it is a really, really bad idea.

tvanfosson
Agreed that its wrong and having the compiler guess is wrong but how else could this be intended?
Leroy Jenkins
Perhaps you intended to use another variable `otherStringName` -- how is the compiler going to know?
tvanfosson
I see what you saying, it just seems redundant. Thanks!
Leroy Jenkins
+11  A: 

I think your proposal would muddy the rules of expression parsing - now, the '==' becomes a quadreny (?) operator, rather than a binary one. I've found myself missing SQL's 'IN' operator, though, and've used something like this:

if (stringName.In("foo", "bar", "baz"))
{

}

// in an extension method class
public static bool In<T>(this T value, params T[] values)
{
    return values.Contains(value);
}
Michael Petrotta
or make it generic: `In<T>(this T value, params T[] values)`
Lucas
@Lucas: excellent suggestion! Incorporated.
Michael Petrotta
+1  A: 

I find the Contains() function solves this problem ie:

string[] ValidNames = new string[] { "firstName", "lastName"};

if(ValidNames.Contains(stringName))
{
    //Do Code
}
Michael La Voie
+1  A: 

I wouldn't mind a SQL like syntax of:

if(stringName in ("firsName", "lastName"))
{
}
Mike J
Looks like Python.
Sarah Vessels
Your answer addresses the intent of the question, instead of the flaw in the OP's suggested syntax, so +1.
Greg
see Petrotta's answer above: http://stackoverflow.com/questions/1615800/c-operators-and-readability/1615835#1615835
Lucas
I can easily see Petrotta's code being what gets generated by the compiler from my syntax.
Mike J
+2  A: 

Even with parentheses, it doesn't make sense. stringName == ("firstName" || "lastName") looks like you want to test the truth of the two strings, and those strings are always going to be true, and then compare that Boolean result with the string stringName.

If you add parentheses like this (stringName == "firstName") || "lastName", the condition is also always going to be true, since "lastName" is always true regardless of whether or not stringName equals "firstName".

I like the Ruby way of doing it:

["firstName", "lastName"].include? stringName

You could always use Contains like others have suggested or write a String extension method to where you could do:

stringName.EqualsOneOf(new[] {"firstName", "lastName"})
Sarah Vessels
+9  A: 

The problem is that if works on booleans.

stringName == "firstName" returns a boolean.
"lastName" is a string literal.

|| is a short-circuited boolean or operator that takes booleans on both sides.

In other words, you want to change the definition of || which is generally a bad idea.

In theory, you could have the parser infer what you mean... but that becomes ambiguous very quickly.

if (stringName == firstName || lastName)

Looks OK, right? But what exactly is lastName?

What if I did this?

const bool lastName = false;

Also, && is the opposite of ||, but stringName == firstName && lastName isn't the opposite of the above logic, and in fact wouldn't make sense.

R. Bemrose
That last line is exactly what I was missing.
Leroy Jenkins
A: 

This is why, as a habit, I always do:

if ((stringName == "firstName") || (stringName == "lastName"))
   // Do code

After a while it becomes second nature.

Andy West
A: 

When the FCL contains the richness to create the sheer variety of answers seen in this thread, you don't need to have a more flexible C# syntax because readability soon becomes a feature of how you create the answer amongst all the richness. It boils itself down to choices between method and object calls much of the time.

Here's an example (just another of many) of being able to locate one or multiple strings simultaneously in an array of strings, or to apply any other criteria you see fit to that set of strings. Indentation, spacing and code comments play a big part for understanding this code sample, as for any code.

        bool found = Array.Exists(
            // array of strings to search
            new[] { "c#", ".net", "programming", "design patterns", "work", "play", "bits", "bytes", "break" },
            // criteria - can even satisfy multiple conditions simultaneously if desired
            str => (str == ".NET" || str == "work") //look for ".NET" or "work"
            );
John K