用于检查具有多个值的相等性的语法糖

本文关键字:语法 检查 用于 | 更新日期: 2023-09-27 18:22:11

我想使用Visual Studio 2015对单个答案4进行compare 2 equations,比如说2*2 and 2+2,例如

if (4 == (2*2 && 2+2)) {...}

但它返回一个错误,"运算符'&&'不能应用于'int'和'int'类型的操作数"。我唯一能想到的写代码的方法是:

if (4 == 2*2 && 4 == 2+2) {...}

这是可行的,但当要比较很多值时,会变得非常重复。有没有更简单的方法来实现这一点?

用于检查具有多个值的相等性的语法糖

var results = new[]{ 2 + 2, 2 * 2, ... };
if (results.All(r => r == 4)) {
    ...
}

这会收集集合results中所有操作的结果,并使用扩展方法All来验证指定的谓词是否适用于所有值;允许只写一次谓词。

您可以编写一个函数:

public static bool AllEqual<T>(T expectedResult, params T[] calculations)
    where T : IEquatable<T>
{
    return calculations.All(x => x.Equals(expectedResult));
}

例如:

if (AllEqual(4, 2 + 2, 2 * 2, 1 + 1 + 1 + 1)) {
    // true
}
if (AllEqual(4, 2 + 2, 2 * 3)) {
    // not true
}

这甚至适用于其他类型,例如

if (AllEqual("foo", "f" + "o" + "o", "fooo".Substring(0, 3))) {
    // true
}

如果您想减少重复,Linq查询可以很好地工作:

IEnumerable<int> fourExpressions = new List<int>{ 2 + 2, 2 * 2, ... };
bool allEqualToFour = fourExpressions.All(x => x == 4);
if (allEqualToFour) { ... }

或作为一行

if (new int[]{ 2 + 2, 2 * 2 }.All(x => x == 4)) { ... }

或者(ab)使用扩展方法以获得最大的简洁性。(一般来说,用这样的辅助方法污染所有对象不是最好的主意,所以这种方法很可能是静态方法。)

public static class QuestionableExtensions
{
    public static bool EqualsAllOf<T>(this T value, params T[] collection) where T : IEquatable<T>
    {
        return collection.All(t => value.Equals(t));
    }
}
public class MyClass 
{
    public void MyMethod()
    {
        if (4.EqualsAllOf(2 * 2, 2 + 2)) { ... }
    }
}

下面的页面有一组很好的链接,用来解释Linq查询。

您可以使用此扩展方法

public static bool SameAs<T>(this T val, params T[] values) where T : struct
{
    return values.All(x => x.Equals(val));
}
if (4.SameAs(2*2,2+2)) { ... }

参考@walpen的回答,指出AllLinq的扩展(在System.Linq.Enumerable中定义)。

我想提供All的.NET 2.0实现,作为扩展。

首先,我们将定义一个名为ExtensionAttributeAttribute。(SO参考:在.NET 2.0中使用扩展方法?)

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class
         | AttributeTargets.Method)]
    public sealed class ExtensionAttribute : Attribute { }
}

然后,(通过魔术的方式)我们可以使用this引用进行扩展。因此,我们将为ExtensionAttribute的使用创建一个static class:我选择通过在System.Collections.Generic命名空间中定义一个名为Enumerablestatic class来实现这一点。

namespace System.Collections.Generic
{
    public static class Enumerable
    {
        //[System.Runtime.CompilerServices.Extension()]
        public static bool All<T>(this IEnumerable<T> list, T expectedAnswer)
            where T : IEquatable<T>, IComparable<T>
        {
            bool result = true;    
            IEnumerator<T> enumerator = list.GetEnumerator();
            while (enumerator.MoveNext())
            {
                result = result && (Object.Equals(enumerator.Current, expectedAnswer));
                if (!result)
                    return result;
            }
            return result;
        }
        public delegate bool MyFunc<T>(T next);

        public static bool All<T>(this IEnumerable<T> list, MyFunc<T> fn)
            where T : IEquatable<T>, IComparable<T>
        {
            bool result = true;    
            IEnumerator<T> enumerator = list.GetEnumerator();
            while (enumerator.MoveNext())
            {
                result = result && fn.Invoke(enumerator.Current);
                if (!result)
                    return result;
            }
            return result;
        }
    }
}

那么,使用它就很简单了

IEnumerable<int> ints = new int[] { 2 + 2, 2 * 2, 1 * 3 + 1 };
Console.Write("Result := {0}", ints.All(4)); // outputs "Result := true"
Console.Write("Result := {0}", ints.All(t => t.Equals(4))); // outputs "Result := true"

只是在中抛出一个随机的想法

if (new Int32[] { 2 * 2, 2 + 2, ... }.All(t => t == 4))
{
    MessageBox.Show("Yup");
}
else
{
    MessageBox.Show("Nope");
}

对不起,对不起我看错了,我删除了以前的代码。这执行OP的逻辑

这是我唯一能找到的办法。