How to correctly add Action and Func<> delegate types to C#2.0?
.NET framework 3.5 introduces Action and Func<> predefined delegate types that are very handy. Is it any way to conditionally add such delegates into my sources so they will compile for both .NET 2.0 and .NET 3.5 without name conflicts? Something like #if not defined( Action ) public delegate void Action(); r #if TARGET_FRAMEWO开发者_JS百科RK < 3.5 public delegate void Action();
Try this:
Open your project, right click on your project in the solution explorer, navigate tot he Build tab, add CSHARP2
in the conditional compilation symbols textbox.
Declare a class called CSharpExtensions.cs:
namespace System
{
#if CSHARP2
public delegate void Action();
public delegate void Action<T>(T t);
public delegate void Action<T, U>(T t, U u);
public delegate void Action<T, U, V>(T t, U u, V v);
public delegate TResult Func<TResult>();
public delegate TResult Func<T, TResult>(T t);
public delegate TResult Func<T, U, TResult>(T t, U u);
public delegate TResult Func<T, U, V, TResult>(T t, U u, V v);
#endif
}
Assuming you compile under 3.5 without defining the CSHARP2 symbol, you should be able to use your functions above as expected:
using System; // includes our new delegates
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static IEnumerable<U> Map<T, U>(IEnumerable<T> input, Func<T, U> f)
{
foreach (T t in input)
{
yield return f(t);
}
}
static void Main(string[] args)
{
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
foreach(String s in Map<int, string>(numbers, delegate(int i) { return String.Format("{0}^2 = {1}", i, i*i); }))
{
Console.WriteLine(s);
}
Console.ReadLine();
}
}
}
When you redefine your Action and Func delegates, they will be in a different namespace and therefore not conflict with anything from .Net 3.5. They'll have the same simple name, signature, and purpose, but the fully qualified name with be different. So no conficts, and no PreProcessor directives needed.
The only caveat is that they will be different from the Action and Func types defined in .Net 3.5. They will work exactly the same. They'll just be different types. This could get you into trouble if you want to call a 3.5 BCL method that takes the original Action type, for example, but since you're shooting for 2.0 compatibility that just shouldn't happen.
If you do a "Go to Definition" in VS on an Action<> or Func<> declaraion, you will see how to declare them. For example Action is declared like this:
public delegate void Action<T>(T obj);
Edit: to check the version of .NET i don't think there's anything predefined. However, you can define a build configuration for each target version and define a symbol there.
I couldn't find a predefined preprocessor variable for you to use, but you can easily set one up in the project properties (in the Build tab). You can switch that flag to whatever you want before building when you switch the version of .NET that you compile against.
I've used this with great success. Define FOR_DOTNET2 when you are building the project ... for .NET 2.0. Even better, you can copy the summary comments over from MSDN and put them in XML format.
#if FOR_DOTNET2
namespace System
{
public delegate void Action<T>(T arg);
}
#endif
You could add them as local to the class where you need them.
public class MyClass
{
// These were not added until .Net 3.5
public delegate void Action();
public delegate TResult Func<TResult>();
public delegate TResult Func<TResult,T>(T arg);
public delegate TResult Func<TResult,T1, T2>(T1 arg1, T2 arg2);
public void DoSomething(Func<int> callback) {
...
}
}
精彩评论