C#泛型以避免代码重复?

时间:2010-09-23 19:53:58

标签: c# generics primitive-types

我对来自Java的C#相当新,我想知道是否有一种简单的方法可以避免代码重复涉及这样的原始类型:


private Boolean AtLeastOneBufferItemIsNonZero(int[] Buffer)
{
    Boolean result = false;
    foreach (int Item in Buffer)
    {
        result = !(Item == (int)0);
        if (result) break;
    }
    return result;
}

private Boolean AtLeastOneBufferItemIsNonZero(float[] Buffer)
{
    Boolean result = false;
    foreach (float Item in Buffer)
    {
       result = !(Item == (float)0);
       if (result) break;
    }
    return result;
}

我找不到一个“数字”超类型,以便我可以在一个泛型实现中比较“Item”(我不介意拳击的性能损失,虽然我明白在.NET中没有这样的东西? ):


//SOMETHING LIKE THIS?
private Boolean AtLeastOneBufferItemIsNonZero<T>(T[] Buffer) where T : NUMBERTYPE
{
    Boolean result = false;
    foreach (T Item in Buffer)
    {
       result = !(Item.Equals(0)); //Nope....
       if (result) break;
    }
    return result;
}

是创建自己的Number实现并使用compare()方法的唯一方法吗?听起来有点矫枉过正了吗?

2 个答案:

答案 0 :(得分:13)

LINQ通过依赖任何数字类型的默认值为零,并且它们具有适当的相等方法,使得这非常简单:

private bool AtLeastOneBufferItemIsNonZero<T>(T[] items)
{
    T zero = default(T);
    EqualityComparer<T> comparer = EqualityComparer<T>.Default;
    return items.Any(t => !comparer.Equals(t, zero));
}

现在不限制它为数字类型,但它确实避免重复。您可以更进一步,将其推广到IEnumerable<T>并将其作为扩展方法:

public static class Extensions
{
    public static bool ContainsNonDefaultValue<T>(this IEnumerable<T> source)
    {
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }
        T zero = default(T);
        EqualityComparer<T> comparer = EqualityComparer<T>.Default;
        return items.Any(t => !comparer.Equals(t, zero));
    }
}

您可以通过将约束更改为

限制为值类型
where T : struct

但这将是一个毫无意义的IMO。通过更改以使用EqualityComparer<T>.Default,您可以 使用该方法检查引用类型序列中的任何值是否为非null。

编辑:作为旁注,另一种看待它的方法是扭转这种情况:

return !items.All(t => comparer.Equals(t, zero));

这取决于你是否对“任何一个非零”或“它们不是全零”的概念感到满意:)

答案 1 :(得分:1)

private Boolean AtLeastOneBufferItemIsNonZero<T>(T[] Buffer)
{
    Boolean result = false;
    foreach (T Item in Buffer)
    {
       result = !Item.Equals(default(T)); //Yep!!!
       if (result) break;
    }
    return result;
}

PS。使用Linq