“Compatibility Pack” for backporting new .NET Fram

2019-02-08 09:20发布

问题:

For various reasons I often find it desirable to write code that is compatible with .NET framework 2.0 or 3.5 or compatible with the .NET Compact Framework, but it is a problem that there are numerous "small" features in new .NET frameworks that are not available in the older frameworks or Compact Framework.

For example, I find extension methods are really useful, but the compiler depends on System.Runtime.CompilerServices.ExtensionAttribute for this. You can easily define this attribute yourself and then use extension methods in .NET Framework 2.0 (under C# 3.0+). Likewise, it isn't too hard to manually define little .NET 4 types like Tuple<T1,T2> and Lazy<T>. By the way, if you want to use LINQ in .NET 2.0, you can use LinqBridge.

Now suppose you make the ExtensionAttribute public so that other assemblies you write can use it. That's fine at first, but what if you then want to use a 3rd party library that also had the same idea? You add a reference to that library and now you've got a name collision. Oops.

I have also noticed that some new libraries are only available for .NET 4.0 or 3.5 even though they only have minor dependencies on it that could be resolved using a compatibility pack or LinqBridge.

It would sure be nice if there were "compatibility packs" for older .NET versions that defined these little features in a small DLL that you could justify including in projects of any size. Does such a thing exist?

Update: Judging by the silence, I guess there's no such thing. I might make such a OSS library myself if there is interest. So my new question is, what smaller features of .NET 4 (as opposed to monsters like WCF/WPF) would you miss if you were writing for .NET 2, .NET 3.5, .NETCF or Silverlight? I'll start the list off...

  • ExtensionAttribute (not in .NET 2)
  • Func<...> and Action<...> delegates (not in .NET 2)
  • LINQ-to-objects (not in .NET 2)
  • Tuple<...> (not in .NET 3.5)
  • Lazy<T> and Lazy<T,TMetadata> (not in .NET 3.5)
  • Expression Trees (not in .NET 2; incomplete in .NET 3.5)
  • Generics Variance (exists in .NET 2 but inaccessible from C# 3 and VB 9)
  • Reflection.Emit (missing from .NETCF; not really a small feature but I miss it very much)

回答1:

Theraot's Libraries

You can use use Theraot.Core from Theraot's Libraries to backport a great portion of .NET code to old versions starting with .NET 2.0 thanks to conditional compilation.

Out of the mentioned features, the following are included:

  • ExtensionAttribute
  • Func<...> and Action<...> delegates
  • LINQ-to-objects
  • Tuple<...>
  • Lazy<T> and Lazy<T,TMetadata>
  • Expression Tress

Also included are the following features not mentioned in the question:

  • HashSet<T>
  • SortedSet<T>
  • ThreadLocal<T>
  • IObservable<T> and IObserver<T>
  • BigInteger
  • ConcurrentDictionary<Tkey, TValue>
  • etc...

Note: Support for System.Threading.Tasks is planned.

Sadly, there is only little documentation available at the moment of writing, yet any difference on behavior from the BCL can be considered a bug, and can be reported via github.



回答2:

This isn't really a "compatilibity pack", but since you mentioned LinqBridge... another "backported feature" I frequently use are the Parallel Extensions found (among other things) in the Reactive Extensions (Rx) for Framework 3.5 SP1 (in System.Threading.dll). It includes full implementation of the Task Parallel Library and Parallel LINQ (PLINQ).

For .Net 4.0 there is the Async Targeting Pack for Visual Studio 2012 (nuget) from Microsoft. Which provides many Async extention methods and provides support for the async/await keywords if using the C# 5 compiler.

Similarly for for .Net 3.5 there is the AsyncBridge that builds on the Reactive Extentions's TPL library to provide async/await. There is also a version of AsyncBridge for .Net 4.0, but I am not sure why you would want that one over the one from Microsoft.



回答3:

For .NET 3.5 you can use FSharp.Core.dll from the F# Runtime for .NET Framework 2.0.

"The core library (FSharp.Core.dll) included in this redistributable package contains some APIs in the System namespaces that are identical to .NET Framework 4 APIs that are required for F# development."

http://msdn.microsoft.com/en-us/library/ee829875%28v=vs.100%29.aspx

This includes System.Tuple et al. and System.Lazy<T>. (Not Lazy<T,TMetadata> though.) To use them just reference FSharp.Core.dll.

Edit: Turns out Lazy in FSharp.Core.dll is not a drop-in replacement, but more of an interop-class. It has the same properties but not the same constructors. Rather it's created e.g. like this:

Lazy<string> lazy = Microsoft.FSharp.Control.LazyExtensions.CreateFromValue("test");


回答4:

I don't know how useful such a list will be, as it is potentially monstrous in size. The CLR is the same for 2.0, 3.0 & 3.5 so tehnically any of these post-2.0 features could make their way into a "compatibilty pack."

-Oisin