2012-12-19 37 views
7

許多自定義可枚舉擴展可以在其他內置的操作來實現 - 比如這個簡單方便的方法:以PLINQ的優勢與自定義可枚舉擴展

public static bool AnyOf<TElement>(this TElement item, IEnumerable<TElement> items) 
{ 
    return items.Any(a => EqualityComparer<TElement>.Default.Equals(a, item)); 
} 

現在,這將迫使任何PLINQ查詢返回順序操作即使PLINQ也具有任何 - 和相當於只用短短簽名更改:

public static bool AnyOf<T>(this T item, ParallelQuery<T> items) 
{ 
    return items.Any(a => EqualityComparer<T>.Default.Equals(a, item)); 
} 

但複製它像這似乎亂了我。

起初我還以爲下面類似的可能工作,但當然不會因爲^擴展方法是靜態方法,因此調用Enumerable.Any而不是ParallelQuery.Any在基於簽名的編譯時作出上述判決。

public static bool AnyOf<TElement, TEnumerable>(this TElement item, TEnumerable items) 
    where TEnumerable : class, IEnumerable<TElement> 
{ 
    return items.Any(a => EqualityComparer<TElement>.Default.Equals(a, item)); 
} 

我來給它不具有不同的簽名創建每個方法的複製是不可能的結論,但也許有件事情我已經錯過了。 (嘖嘖始終與不可能的問題!)


也許會從並行化中獲益的幫手(顯然可以鏈接等),一個更好的例子是這樣的。

public static IEnumerable<string> ToStrings(this IEnumerable<object> ienum) 
{ 
    return ienum.Select(a=> a.ToString()); 
} 

^編譯器錯誤:

The type 'ParallelQuery<TElement>' cannot be used as type parameter 
'TEnumerable' in the generic type or method 
'AnyOf<TElement,TEnumerable>(TElement, TEnumerable)'. There is no 
implicit reference conversion from 'ParallelQuery<TElement>' to 
'IEnumerable<TElement>' 

也是值得考慮的是,並不是所有的ParallelQuery的/可枚舉的方法是等效的,即使他們不編譯。

+0

什麼實際問題? – jessehouwing

+1

恩,呃。有點被帶走了:「有沒有什麼方法可以編寫一個LINQ擴展,這個擴展也適用於PLINQ?」。 – Fowl

+0

你所有的擴展方法都很簡短嗎?你有多少人? – svick

回答

1

我已經做了類似的寫作IQueryable/IEnumerable擴展。試圖將常見的位分解出來,包括聲明靜態變量保存表達式,然後從函數的兩個不同版本中引用該表達式。我再也沒有這些代碼,當我完成時,它非常難看,我對此並不滿意。這是一個微不足道的例子。

Expression<Func<PersonHistory, bool>> IsCurrent = (p) => p.Ends > DateTime.Now && p.Starts <= DateTime.Now; 

//Then in each Extension method: 
var query = db.PersonHistories.Where(IsCurrent); 

最終,重複數據刪除的水平根本不好,並且通過泛型參數會變得更加複雜。也許這會給你一個想法。

期待看到別人的想法。

1

你可以通過做這個檢查的方法(即運行時切換)內,像這樣鑄造:

public static bool AnyOf<TElement>(this TElement item, IEnumerable<TElement> items) 
{ 
    var parallelItems = items as ParallelQuery<TElement> 
    if(parallelItems != null) 
    { 
     return parallelItems.Any(a => EqualityComparer<TElement>.Default.Equals(a, item)) 
    } 
    //other runtime checks 
    .... 
    //else return default IEnumerable implementation 
    return items.Any(a => EqualityComparer<TElement>.Default.Equals(a, item)); 
} 
+0

這有什麼幫助?仍然意味着你有兩次相同的代碼。 – svick

+0

@svick ala'我得出的結論是,如果不用不同的簽名創建每個方法的副本是不可能的,但也許有一些我錯過了'&'有沒有什麼方法可以編寫一個也可以工作的LINQ擴展用PLINQ?「他的實際問題不是寫兩次,而是根據枚舉行爲有一個聰明的簽名,這是一個解決方案 – user1793607

+2

但我相信這樣做的根本原因是爲了避免代碼重複。 – svick