将裸null文本与用户定义的运算符一起使用时的好奇重载决策

时间:2012-10-25 16:15:32

标签: c# null operator-overloading overload-resolution lifted-operators

(标题中的“用户定义”是指TimeSpanDateTime的加法和减法不是C#标准的一部分。它们在BCL中定义。)

使用可取的TimeSpanDateTime值的提升运算符,我编写了以下代码。请注意,该框架在TimeSpanDateTime上提供了不同的操作。

有一个对称(和可交换)的加法,你可以接收两个TimeSpan并返回总和TimeSpan。这个加法的“逆”是减去两个TimeSpan,产生TimeSpan

然后还有另一种不对称的加法,你可以用一个DateTime(左操作数)和一个TimeSpan(右操作数)来产生一个DateTime。由于此操作的不对称性,它有两种“反转”类型:一种是相互减去两个DateTime以获得TimeSpan差异,另一种是DateTime的{​​{1}}。并从中减去一个TimeSpan以生成结果DateTime

static void Main()
{
  DateTime? n_dt = new DateTime(2012, 12, 25);
  TimeSpan? n_ts = TimeSpan.FromDays(62.0);

  var a = n_dt + n_ts;   // OK
  var b = n_ts + n_ts;   // OK

  var c = null + n_dt;   // OK, string concatenation! Type of expression is String
  var d = null + n_ts;   // OK, compiler prefers TS+TS, not DT+TS
  var e = n_dt + null;   // OK, DT+TS
  var f = n_ts + null;   // OK, TS+TS
  var g = null + null;   // error, type of expression is undetermined

  var h = n_dt - n_dt;   // OK
  var i = n_dt - n_ts;   // OK
  var j = n_ts - n_ts;   // OK

  var k = null - n_dt;   // OK, DT-DT
  var l = null - n_ts;   // compiler prefers TS-TS, not DT-TS
  var m = n_dt - null;   // error, compiler won't choose between DT-DT amd DT-TS, type of expression is undetermined
  var n = n_ts - null;   // OK, TS-TS
  var o = null - null;   // OK, integer subtraction! Type of expression is Nullable<Int32>

  // illegal:
//var p = n_dt + n_dt;
//var q = n_ts + n_dt;
//var r = n_ts - n_dt;
}

自然会出现一些问题。

有些奇怪的是o被允许并提供int?(顺便提一下,为什么不是long??),而g是不被允许的。这是规格吗?另外,通过字符串连接解决“不可能的”c有点奇怪。显然,编译器决定null中的c(string)null。另一方面,将显式类型object的表达式添加到DateTime将无法编译。

但我的主要问题是:为什么编译器会为dl选择一个重载,但是m它会抱怨模糊不清?

1 个答案:

答案 0 :(得分:0)

原因似乎是m,两种可能的操作在同一类型中是定义,即System.DateTime。没有办法在它们之间做出选择。

另一方面,对于dl,一个操作在System.TimeSpan中定义,另一个在System.DateTime中定义。但是在dl的行中,我们看到TimeSpan,但在DateTime的分配中没有提到任何d类型的内容。 l。似乎编译器只搜索类型System.TimeSpan中定义的运算符,并忘记搜索所有其他类型中定义的用户定义的运算符(顺便说一下,搜索的类型很多)。这样,在dl的解析过程中,编译器永远不会发现DateTime类型中定义的运算符。