2009-11-09 36 views
2

.NET Framework 3.5的推出是非常方便的操作和Func键<>预定义的委托类型。是否有条件地将这些委托添加到我的源代码中,以便它们可以针对.NET 2.0和.NET 3.5进行编译而不会发生名称冲突?类似#if未定义(Action)public delegate void Action(); r #if TARGET_FRAMEWORK < 3.5 public delegate void Action();如何正确添加Action和Func <>委托类型到C#2.0?

+0

没有C#3.5 - Action和Func <>是.Net 3.5框架中的类型。 C#3.0有一些语法(如var和lambdas)来帮助使用这些类型。 – 2009-11-09 15:45:56

+0

感谢您的评论,我编辑了一个问题来澄清它。 – grigoryvp 2009-11-09 15:47:53

回答

1

当你重新定义你的行动和Func键代表,他们将在不同的命名空间,因此不与NET 3.5的任何冲突。他们将具有相同的简单名称,签名和用途,但完全限定的名称会有所不同。所以不要混淆,也不需要PreProcessor指令。

唯一需要注意的是,他们将不同的与.NET 3.5中定义的Action和Func类型不同。他们将工作完全一样。他们只是不同的类型。例如,如果您想调用采用原始动作类型的3.5 BCL方法,但这会使您陷入麻烦,但是因为您正在拍摄2.0版本的兼容性,所以不会发生这种情况。

+0

但我需要为它们使用完全限定的名称,对吧?如果我同时使用系统 ;使用MyDelegateTypes的 ; 如果使用.NET 3.5目标进行编译,会导致名称冲突?或不? – grigoryvp 2009-11-09 15:49:40

+0

编号操作和Func位于基本的System命名空间中,但它们实际上是在System.Core程序集中定义的,您不应该加载该程序集,因为这会导致2.0编译出现问题。 – 2009-11-09 15:54:00

+0

我刚刚编译了一个只使用System的测试代码;并使用MyDelegates ;.它给编译错误关于System.Action和MyDelegates.Action之间的名称冲突:( – grigoryvp 2009-11-09 15:58:27

1

如果你在一个动作<>或者函数<>声明中的VS中执行“定义”,你会看到如何声明它们。例如Action声明如下:

public delegate void Action<T>(T obj); 

编辑:检查.NET的版本我不认为有任何预定义。但是,您可以为每个目标版本定义一个构建配置,并在其中定义一个符号。

+0

我知道。但我需要一种方法来声明它们仅适用于C#2.0,所以如果我的代码是在c#3.5中编译的,那么名称将不会发生冲突。 – grigoryvp 2009-11-09 15:42:42

0

你可以它们作为本地添加到你需要它们的类。

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) { 
     ... 
    } 
} 
+0

将它们添加到所有类是很多代码:(。也许这是一些#if只有当它们还没有被定义时才允许定义它们。像#if未定义(Func)...或#if COMPILER_VERSION <3.5 ... – grigoryvp 2009-11-09 15:43:48

1

我找不到你使用预定义的预处理器变量,但你可以很容易地设置一个项目属性(在Build标签)。在切换您编译的.NET版本时,您可以在构建之前将该标志切换为任何想要的标志。

+0

是的,这听起来很奇怪就像一种解决方案,如果没有找到更好的东西,我会使用它,但是对于特定的构建而言,特定的预处理器变量会导致构建过程复杂化,这不是一件很好的事情:(. – grigoryvp 2009-11-09 15:52:30

3

试试这个:

打开你的项目,右键单击您的项目在解决方案资源管理器,导航托特他建立选项卡,在条件编译符号文本框添加CSHARP2

声明一个类调用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 
} 

假设你在3.5 编译不定义CSHARP2符号,你应该能够使用上面的功能预期:

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(); 
     } 
    } 
} 
+3

这是.NET 2.0,不是C#2.0,所以命名为'CSHARP2'是非常具有误导性的。 – 2009-11-09 16:07:27

1

我已经使用这个很成功。在.NET 2.0中构建项目时定义FOR_DOTNET2。更妙的是,您可以从MSDN中复制摘要注释并将其放入XML格式。

#if FOR_DOTNET2 
namespace System 
{ 
    public delegate void Action<T>(T arg); 
} 
#endif