这件大事复杂吗?或这个?或这个?

Joe*_*Joe 26 c# idiomatic operators

假设我正在使用类的对象thing.我得到这个对象的方式有点罗嗦:

 BigObjectThing.Uncle.PreferredInputStream.NthRelative(5)
Run Code Online (Sandbox Code Playgroud)

我想看看这thing是否等于xyz.写这个的天真方式可能是:

 BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == x ||
 BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == y ||
 BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == z
Run Code Online (Sandbox Code Playgroud)

在某些语言中,我可以这样写:

 BigObjectThing.Uncle.PreferredInputStream.NthRelative(5) == x |= y |= z
Run Code Online (Sandbox Code Playgroud)

但C#不允许这样做.

是否有一种C#-idiomatic方法将此测试编写为单个表达式

Jac*_*cob 46

只需使用变量:

var relative = BigObjectThing.Uncle.PreferredInputStream.NthRelative(5);
return relative == x || relative == y || relative == z;
Run Code Online (Sandbox Code Playgroud)

或者如果你想得到更多的东西:

var relatives = new HashSet<thing>(new[] { x, y, z });
return relatives.Contains(BigObjectThing.Uncle.PreferredInputStream.NthRelative(5));
Run Code Online (Sandbox Code Playgroud)

  • @Joe:最好的答案通常可以解决问题,而不是回答问题.这个**是最好的答案; 在C#中,将函数调用的结果与多个事物进行比较的最惯用的方法是将其分配给变量.任何其他方法_(例如滥用`Contains()`)_都是非惯用的,并且只会模糊代码的目的. (35认同)
  • @ BlueRaja-DannyPflughoeft:"最好的答案通常可以解决问题,而不是回答问题",但这应该是*明确*而不是*隐含*.也就是说 - 可以说"没有惯用的方法可以将其作为单个表达式",但是默默地忽略这就是所要求的并不好.所以最初发布的答案是不完整的. (5认同)
  • 我特别要求如何将*作为单个表达式*. (3认同)
  • 您也可以内联`relatives`来获得"单个语句",但它的可读性较低(有时在链接的LINQ语句中也很有用).(只使用数组可能足够3个项目 - (new [] {x,y,z}).包含...`) (2认同)

C.E*_*uis 24

扩展方法会模拟这个:

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);
Run Code Online (Sandbox Code Playgroud)

C#没有这种类似OR的比较afaik的默认语法.

  • 请记住,`Contains`使用`Equals`而不是`==`,这是OP正在使用的.这些并不总是一样的. (10认同)
  • 你也可以做这个通用的 (2认同)
  • 如果`this`参数的类型为`Thing`,则数组应为`params Thing [] compare`.或者你可以使方法更通用,并使第一个参数`object`,但我觉得这两个参数的类型应该一致.但是@ aw04的建议让它变得通用是有道理的. (2认同)

mcl*_*129 14

正如其他人指出的那样,集合是你可以做到这一点的一种方式.如果你想有比使用多一点的灵活性Contains(这只有真正让你测试x.Equals(y)),甚至支持链接通过&=在additon来|=,我会建议AnyAll内置到.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);
Run Code Online (Sandbox Code Playgroud)


Set*_*eth 10

您可以将对象放在Collection第一个然后使用Contains().

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

这可以进一步缩短(为了便于阅读):

if (new Collection<Thing> { x, y, z }.Contains(BigObjectThing.Uncle.PreferredInputStream.NthRelative(5)))
{
    ...
}
Run Code Online (Sandbox Code Playgroud)