2010-09-23 142 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