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

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 } 

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

DateTime 不能显式转换为 Nullable

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

在以下情况下,扩展方法符

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

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

因此,您必须显式地将DateTimeNullable或者从头开始使用可为空的:

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

要么

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

正如蒂姆所说,可以为空

固定:

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

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

var变量也称为隐式类型局部变量(C#编程指南)

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

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

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

 DateTime? dateTimeNullable = DateTime.Now; dateTimeNullable.GenericMethod(); int? intNullable = 0; intNullable.GenericMethod(); 

因为你为DateTime?写了一个扩展名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 

将工作。

你现在需要创建你的变量,其中corret类型为nullable,如下所示:

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