(标题中的“用户自定义”是指TimeSpan
和DateTime
的加减不是C#标准的一部分,它们是在 BCL 中定义。)
在可为空的 TimeSpan
和 DateTime
值上使用提升运算符,我编写了以下代码。请注意,该框架在 TimeSpan
和 DateTime
上提供了不同的操作。
有一个对称(和交换)加法,您接受两个 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
将不会编译。
但我的主要问题是:为什么编译器可以为 d
和 l
选择重载,但对于 m
它会报错关于歧义?
最佳答案
原因似乎是对于 m
,两种可能的操作是在同一类型内定义的,即 System.DateTime
。无法在它们之间进行选择。
另一方面,对于 d
和 l
,一个操作定义在 System.TimeSpan
中,另一个定义在System.DateTime
。但是在 d
和 l
的行中,我们看到了 TimeSpan
,但是没有提到任何 DateTime
类型是什么在 d
和 l
的赋值中也是如此。似乎编译器然后只搜索 System.TimeSpan
类型中定义的运算符,而忘记搜索所有其他类型中定义的用户定义运算符(顺便说一下,这些类型可能有很多)搜索)。这样,在解析 d
和 l
期间,编译器永远不会发现 DateTime
类型中定义的运算符。
关于c# - 将裸空文字与用户定义的运算符一起使用时奇怪的重载解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13072864/