c# - 将裸空文字与用户定义的运算符一起使用时奇怪的重载解决方案

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

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

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

有一个对称(和交换)加法,您接受两个 TimeSpan 并返回总和 TimeSpan。此加法的“逆运算”是两个 TimeSpan 的减法,得到一个 TimeSpan

还有另一种加法,非对称加法,您可以用一个 DateTime(左操作数)和一个 TimeSpan(右操作数)生成一个 DateTime。由于此操作的不对称性,它有两种“类型”的逆运算:一种是将两个 DateTime 彼此相减以获得 TimeSpan 差值,另一种是您有一个 DateTime 并从中减去一个 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 是通过字符串连接来解决的,这有点奇怪。显然,编译器决定 c 中的 null(string)null。另一方面,将显式类型 object 的表达式添加到 DateTime 将不会编译。

但我的主要问题是:为什么编译器可以为 dl 选择重载,但对于 m 它会报错关于歧义?

最佳答案

原因似乎是对于 m,两种可能的操作是在同一类型内定义的,即 System.DateTime。无法在它们之间进行选择。

另一方面,对于 dl,一个操作定义在 System.TimeSpan 中,另一个定义在System.DateTime。但是在 dl 的行中,我们看到了 TimeSpan,但是没有提到任何 DateTime 类型是什么在 dl 的赋值中也是如此。似乎编译器然后只搜索 System.TimeSpan 类型中定义的运算符,而忘记搜索所有其他类型中定义的用户定义运算符(顺便说一下,这些类型可能有很多)搜索)。这样,在解析 dl 期间,编译器永远不会发现 DateTime 类型中定义的运算符。

关于c# - 将裸空文字与用户定义的运算符一起使用时奇怪的重载解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13072864/

相关文章:

c# - 从 aspx 向 Firefox 提供一个 exe。 Firefox 将其下载为 "Content"。文件名不正确且没有扩展名

c# - 这个宽度的数据类型是什么?

c# - 对象引用静态成员垃圾处理

MySQL 检查空白或空值

sql - Psql not null 错误但值不为空

c# - 如何从socket连续接收数据?

null - 零安全的好处

C++ 模板类的运算符

c++ - 赋值运算符不应该返回 "empty"实例?

c++ - 重载的 operator= 返回 void 不可能是复制赋值运算符吗?