2012-07-05 92 views
13

當我嘗試使用.NET 2.0或3.0運行時,我得到的錯誤添加一個擴展方法:我可以在.NET 2.0或3.0中使用擴展方法和LINQ嗎?

Cannot define a new extension method because the compiler required type 'System.Runtime.CompilerServices.ExtensionAttribute' cannot be found. Are you missing a reference to System.Core.dll?

但在可用引用的列表,我找不到System.Core程序,當我嘗試將其添加到項目中。我需要做什麼才能夠使用擴展方法,然後在我的項目中使用LINQ

回答

28

擴展方法直到3.5才被添加到.NET中。但是,這不是對CLR的更改,而是添加了它們的a change to the compiler,因此您仍然可以在2.0和3.0項目中使用它們!唯一的要求是您必須有一個可以創建3.5項目的編譯器才能執行此解決方法(Visual   Studio   2008及更高版本)。

當您嘗試使用擴展方法時出現錯誤,因爲您確實不需要System.Core.dll才能使用擴展方法,因此會產生誤導。當您在後臺使用擴展方法時,編譯器將[Extension]屬性添加到該函數。如果你有一個理解如何處理[Extension]屬性的編譯器,你可以在你的2.0和3.0項目中使用它,如果你自己創建屬性的話。

只是下面的類添加到您的項目,然後就可以開始使用擴展方法:

namespace System.Runtime.CompilerServices 
{ 
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] 
    public class ExtensionAttribute : Attribute 
    { 
    } 
} 

上面的代碼塊坐在裏面System.Core.Dll,所以這就是爲什麼錯誤說你需要包括DLL文件來使用它們。


現在,如果你想要LINQ功能,將需要一些額外的工作。您將需要自己重新實施擴展方法。爲了模擬完整的LINQ to SQL功能,代碼可能會變得非常複雜。但是,如果您只是使用LINQ to Objects,大多數LINQ方法實現起來並不複雜。這裏有幾個LINQ  到 對象替換功能,我從一個項目中寫出來讓你開始。

public static class LinqReplacement 
{ 
    public delegate TResult Func<T, TResult>(T arg); 
    public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2); 

    public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 
    { 
     if (source == null) 
      throw new ArgumentNullException("source"); 
     if (predicate == null) 
      throw new ArgumentNullException("predicate"); 

     foreach (TSource item in source) 
     { 
      if (predicate(item) == true) 
       return item; 
     } 

     throw new InvalidOperationException("No item satisfied the predicate or the source collection was empty."); 
    } 

    public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source) 
    { 
     if (source == null) 
      throw new ArgumentNullException("source"); 

     foreach (TSource item in source) 
     { 
      return item; 
     } 

     return default(TSource); 
    } 

    public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) 
    { 
     foreach (object item in source) 
     { 
      yield return (TResult)item; 
     } 
    } 

    public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector) 
    { 
     if (source == null) 
      throw new ArgumentNullException("source"); 
     if (selector == null) 
      throw new ArgumentNullException("selector"); 

     foreach (TSource item in source) 
     { 
      foreach (TResult subItem in selector(item)) 
      { 
       yield return subItem; 
      } 
     } 
    } 

    public static int Count<TSource>(this IEnumerable<TSource> source) 
    { 
     var asCollection = source as ICollection; 
     if(asCollection != null) 
     { 
      return asCollection.Count; 
     } 

     int count = 0; 
     foreach (TSource item in source) 
     { 
      checked //If we are counting a larger than int.MaxValue enumerable this will cause a OverflowException to happen when the counter wraps around. 
      { 
       count++; 
      } 
     } 
     return count; 
    } 
} 

與LINQ  的全重,以實行對象 已添加在ExtensionAttribute庫可以在LinqBridge項目(感謝Allon Guralnek)被發現。

+0

重要的是要指出,您的LinqReplacement方法將只適用於Linq到對象。它不適用於Linq to Sql。好像很多人沒有意識到有什麼不同。但仍然+1 – cadrell0 2012-07-05 14:46:40

+0

您不必自己重新實施擴展方法。很久以前,[LINqBridge](http://linqbridge.googlecode.com/)已經爲.NET 2.0重新實現了完整的LINQ-to-Objects提供程序。它已經包含了'ExtensionAttribute',它允許你在.NET 2.0及以上版本的.NET 2.0中創建擴展方法。 – 2012-07-05 14:52:15

+0

@AllonGuralnek感謝您的鏈接,更新了答案並給了您信任。 – 2012-07-05 14:56:24

相關問題