具有可空值类型参数的扩展方法解析

时间:2014-02-25 13:41:21

标签: c# compiler-construction overloading extension-methods

public static class Extension
{
    public static void Test(this DateTime? dt)
    {
    }
}


void Main()
{
    var now = DateTime.Now;
    Extension.Test(now); // ok
    now.Test(); // compile time error
}

我只是好奇,为什么编译器在作为扩展名调用时无法解析相同的方法?

5 个答案:

答案 0 :(得分:3)

DateTime明确not convertible to Nullable<DateTime>

C#规范,7.6.5.2扩展方法调用:

如果符合以下条件,则扩展方法符合条件:

  • 当作为静态方法应用于参数时,Mj是可访问且适用的,如上所示
  • 从expr到Mj的第一个参数的类型存在隐式标识,引用或装箱转换。

...

如果在任何封闭的命名空间声明或编译单元中找不到候选集,则会发生编译时错误。

所以你必须明确地将DateTime强制转换为Nullable<DateTime>,或者从一开始就使用可空的东西:

DateTime now = DateTime.Now;
((DateTime?)now).Test();

DateTime? now = DateTime.Now;
now.Test();

答案 1 :(得分:1)

正如蒂姆所说的可以犯罪+1

修正:

  public static class Extension
  {
    public static void Test(this DateTime? dt)
    {
    }
  }

  public class Program
  {
    private void Main()
    {
      DateTime? now = DateTime.Now;
      Extension.Test(now); 
      now.Test();  
   }
  }

答案 2 :(得分:1)

var不是一种类型。实际类型在编译时计算出来。如果您为DateTime.Now设置var,它会识别为DateTime类型,而不是Nullable<DateTime>,这就是它无法编译的原因。

var个变量也称为Implicitly Typed Local Variables (C# Programming Guide)

顺便说一句,您还可以为可空类型创建通用扩展方法:

public static T? GenericMethod<T>(this T? source) where T : struct
{
    //Do something
}

你可以调用任何可以为空的东西,声明它的类型:

DateTime? dateTimeNullable = DateTime.Now;
dateTimeNullable.GenericMethod();

int? intNullable = 0;
intNullable.GenericMethod();

答案 3 :(得分:0)

因为您为DateTime?而不是DateTime编写了扩展程序。

        DateTime? now = DateTime.Now;
        Extension.Test(now); // ok
        now.Test(); // no compile time error

        var now = new DateTime?(DateTime.Now);
        Extension.Test(now); // ok
        now.Test(); // no compile time error

会奏效。

答案 4 :(得分:0)

现在需要使用正确的类型nullable创建变量,如下所示:

 DateTime? dateTime = DateTime.Now;
 dateTime.Test();