C#运算符和可读性

C#运算符和可读性,c#,compiler-construction,operators,C#,Compiler Construction,Operators,我正在写一些代码,发现自己犯了这个错误 if (stringName == "firstName" || "lastName") // Do code 显然,这是错误的,应该予以纠正 if (stringName == "firstName" || stringName == "lastName") // Do code 但这让我想到了可读性,第一个会更容易吗?也许有一些逻辑可以说,除非指定了新的stringName,否则使用第一个 真的不是问题,我只是好奇在编译这样一个语句

我正在写一些代码,发现自己犯了这个错误

if (stringName == "firstName" || "lastName")
   // Do code 
显然,这是错误的,应该予以纠正

if (stringName == "firstName" || stringName == "lastName")
   // Do code 
但这让我想到了可读性,第一个会更容易吗?也许有一些逻辑可以说,除非指定了新的stringName,否则使用第一个


真的不是问题,我只是好奇在编译这样一个语句背后的逻辑是否有什么我不完全理解的地方。

他们不允许使用这种语法的原因很可能是因为可读性。如果您是第一次查看代码,并且您的思维状态不是很好,您可能不会立即看到您正在将
stringName
“firstName”
“lastName”
进行比较。它只是让你的意图更加明确


同样,括号可能会解决这个问题。

只有当
操作符| | |(字符串,字符串)
返回时,这才有效。。一种字符串集合,您有一个
Equals
重载,它获取一个字符串和该字符串集合,并验证该字符串是否在集合中。对于一个很少使用的构造,似乎有很多工作是在幕后完成的

特别是因为你已经可以做一些事情了,比如:

if(new string[]{"firstName","lastName"}.Contains(stringName))
    // code

当代码明显错误时,让编译器猜测程序员的意图以修复它是一个非常非常糟糕的主意。

我认为你的建议会弄乱表达式解析的规则-现在,'=='变成一个四元(?)运算符,而不是二元运算符。不过,我发现自己缺少SQL的“IN”运算符,并使用了类似的方法:

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);
}
if(stringName.In(“foo”、“bar”、“baz”))
{
}
//在扩展方法类中
公共静态布尔输入(此T值,参数T[]值)
{
返回值。包含(值);
}
我发现Contains()函数解决了这个问题,即:

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

if(ValidNames.Contains(stringName))
{
    //Do Code
}

我不介意使用类似SQL的语法:

if(stringName in ("firsName", "lastName"))
{
}

即使有括号,也没有意义
stringName==(“firstName”| |“lastName”)
看起来您想要测试两个字符串的真实性,并且这些字符串总是为真,然后将该布尔结果与字符串
stringName
进行比较

如果像这样添加括号
(stringName==“firstName”)| |“lastName”
,则条件也将始终为真,因为无论
stringName
是否等于
firstName

我喜欢Ruby的工作方式:

["firstName", "lastName"].include? stringName
您可以像其他人建议的那样使用
Contains
,或者编写一个字符串扩展方法,以便执行以下操作:

stringName.EqualsOneOf(new[] {"firstName", "lastName"})

问题是if对布尔型有效

stringName==“firstName”
返回一个布尔值。
“lastName”
是字符串文字

| |
是一个短路布尔or运算符,两边都使用布尔值

换句话说,您想要更改
| |
的定义,这通常是个坏主意

理论上,你可以让解析器推断出你的意思。。。但这很快就会变得模棱两可

if (stringName == firstName || lastName)
看起来还好吧?但到底姓什么呢

如果是我干的呢

const bool lastName = false;

另外,
&
|
的对立面,但是
stringName==firstName&&lastName
不是上述逻辑的对立面,事实上也没有意义。

这就是为什么作为习惯,我总是这样做的原因:

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

过了一段时间,它就变成了第二天性。

当FCL包含丰富的内容来创建此线程中看到的各种各样的答案时,您不需要有更灵活的C#语法,因为可读性很快就成为您在所有丰富内容中创建答案的一个特点。它在很大程度上归结为方法调用和对象调用之间的选择

这里有一个例子(只是许多例子中的另一个),可以在字符串数组中同时定位一个或多个字符串,或者将您认为合适的任何其他条件应用于该字符串集。 缩进、间距和代码注释对于理解此代码示例和任何代码都起着重要作用

        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"
            );

那是品味的问题。如果你说这是浪费,那么我同意,它创建一个数组只是为了比较一些值。同样的技术在其他语言中肯定更具可读性:
如果stringName in(“firstName”,“lastName”)…
(Python)同意这是错误的,让编译器猜测是错误的,但这又怎么可能呢?也许你打算使用另一个变量
otherStringName
——编译器怎么知道呢?我明白你的意思了,这似乎是多余的。谢谢最后一行正是我所缺少的。你的回答说明了问题的意图,而不是OP建议的语法中的缺陷,因此+1。请参见上面Petrotta的回答:我可以很容易地看到Petrotta的代码是编译器根据我的语法生成的。或者将其作为泛型:
in(此T值,参数T[]值)
您可以使用运算符重载。例如,您可以创建一个包含字符串列表的类(我们称之为foo),使用操作符重载:make string | | string return foo(显然,容器中有字符串),make foo | | string应该添加字符串并返回foo。(因此您可以使用string | string | string)然后可以重载string==foo,以便最终比较它们。那么,简短的回答?操作员超载岩石!