2010-09-23 113 views
5

我是相当新的C#从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; 
} 

我无法找到一个“号码”超这样我可以在一个泛型实现比较“项目”(我不介意拳击的性能损失,但据我所知,在.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; 
} 

是对的唯一途径创建我自己的数字实现并有一个compare()方法?这听起来像是矫枉过正不是吗?

+0

有一些类似的问题。检查他们是否帮助你。的例子夫妇:http://stackoverflow.com/questions/3329576/generic-constraint-to-match-numeric-types http://stackoverflow.com/questions/802024/struggling-to-come-up-with-a -generic-C-方法 - 即 - 比较 - 不同类型-的正 – Carlos 2010-09-23 19:58:11

+0

在一个侧面说明,使用'bool'代替'Boolean'。布尔是一个捷径。 – GenericTypeTea 2010-09-23 20:00:40

回答

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,你可以使用的方法来检查引用类型序列的任何值是否非空。

编辑:作为一个方面说明,一脸的另一种方式它是反转条件:

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

这取决于你是否是与概念快乐“他们中任何一个非零”或“它们不全为零”:)

+0

但是,它会返回一个值,指示至少有一个项*是否为零? – 2010-09-23 19:59:11

+0

@Fredrik:卫生署,是的 - 固定... – 2010-09-23 20:00:03

+0

但应该不是那么被命名为'AtLeastOneBufferItemIsZero'? – 2010-09-23 20:00:33

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