C# ? 构造函数处理可为null的类型

C# ? 构造函数处理可为null的类型,c#,datetime,nullable,C#,Datetime,Nullable,小问题,只是为了理解:我有2个可为空的日期时间。我读出了创建时间和更新时间,两者都可以填写。因此,我想检查哪个是稍后的: lastChangedIndrole = (tmpCreate > tmpUpdate ? tmpCreate : tmpUpdate); 但是这里发生了一些奇怪的事情。当f.e.tmpUpdate为null时,我希望抛出一个错误,但它似乎返回了一些东西,但不是corret值,而是第二个值,在我的示例中是update 有什么我不明白的吗?我认为代码会检查毫秒到1900

小问题,只是为了理解:我有2个可为空的日期时间。我读出了创建时间和更新时间,两者都可以填写。因此,我想检查哪个是稍后的:

lastChangedIndrole = (tmpCreate > tmpUpdate ? tmpCreate : tmpUpdate);
但是这里发生了一些奇怪的事情。当f.e.tmpUpdate为null时,我希望抛出一个错误,但它似乎返回了一些东西,但不是corret值,而是第二个值,在我的示例中是update

有什么我不明白的吗?我认为代码会检查毫秒到1900,如果有空值,就会抛出错误。但这并没有发生。这是我不懂的魔法吗

附言:有没有一个特别的词来形容这个词?像vb中的IIF这样的构造函数?很难找到什么

谢谢,本周有一个良好的开端


Matthias

可为null.Value
读取时,可为null的类型将引发异常。但它在比较时不会抛出异常,但会给出意外的结果(将
null
与非null值进行比较永远不会返回true)

下面的代码片段将说明这个问题

DateTime? dt1 = null;
DateTime? dt2 = DateTime.Now;

bool b1 = dt2 > dt1;//false(we expect true here)
bool b2 = dt2 < dt1;//false
bool b3 = dt2 == dt1;//false
DateTime?dt1=null;
约会时间?dt2=日期时间。现在;
boolb1=dt2>dt1//false(此处我们期望为true)
boolb2=dt2
这种行为被记录在案

与可为null的类型进行比较时,如果其中一个可为null的类型的值为null,而另一个不为null,则除!=(不相等)。重要的是不要假设因为一个特定的比较返回false,相反的情况返回true。在下面的示例中,10不大于、小于或等于null。只有num1!=num2的计算结果为true

C#将
运算符提升到可为null的类型上,如果其中一个参数为null,它们将返回
false

因此,如果
tmpCreate
tmpUpdate
为空,则
tmpCreate>tmpUpdate
的计算结果为
false

规范中对其进行了描述:

7.3.7起重操作人员

•对于关系运算符<>= 如果操作数类型都是不可为空的值类型,则运算符存在 如果结果类型是bool。提升模板由以下构件构成: 添加单个?每个操作数类型的修饰符。被提升的操作员 如果一个或两个操作数都为null,则生成值false。否则,, 提升运算符展开操作数并应用基础 运算符生成布尔结果


您可以比较两个
DateTime?
对象,但大多数情况下,当至少一个操作数为
null
时,结果将为
false

例如:

DateTime? today = DateTime.Today;
DateTime? yesterday = DateTime.Today.AddDays(-1);
DateTime? nodate = null;
DateTime? nodate2 = null;

Console.WriteLine(today > yesterday); //true
Console.WriteLine(today < yesterday); //false

Console.WriteLine(today > nodate); //false
Console.WriteLine(today == nodate); //false
Console.WriteLine(today < nodate); //false

Console.WriteLine(nodate > yesterday); //false
Console.WriteLine(nodate == yesterday); //false
Console.WriteLine(nodate < yesterday); //false

Console.WriteLine(nodate > nodate2); //false
Console.WriteLine(nodate == nodate2); //true - this is the exception
Console.WriteLine(nodate < nodate2); //false

当您将可为Null的值与其他可为Null的值或不可为Null的值进行比较时,不可为Null的类型上的运算符将被“提升”,因此也将应用于其对应的可为Null的值

但是,特殊处理将处理其中一个或两个都为null的情况

下面是一个例子:

输出:

False
False
False
True
如您所见,当比较两个可为null的int时,其中一个为
null
,只有相等运算符产生预期结果

如果我们将
a
变量设为不可为空的int:

int a = 10;
但如果保留代码,则会产生完全相同的结果

如果两者都为空呢

int? a = null;
int? b = null;
产生:

False
False
True
False
结论:

  • 相等运算符(
    =
    !=
    )正确处理具有可空类型的
    null
    s
  • 小于或大于运算符不返回,如果其中一个操作数为
    null
    ,即使您切换比较,它们也将返回
    false
    。基本上,
    10
    既不小于也不大于
    null
如果尝试读取
null
可为null的类型值的
.Value
属性,它将引发异常,但运算符不会直接访问
.Value
属性,而是首先检查
.HasValue
属性,然后在尝试实际比较之前处理这些情况。

使用
^
(xor)检查是否只有一个条件为真(等于null),然后
??
返回第一个NOTNULL值。如果两者都不为null,则使用现有表达式

if (tmpCreate == null ^ tmpUpdate == null)
   lastChangedIndrole = tmpCreate ?? tmpUpdate;
else
   lastChangedIndrole = (tmpCreate > tmpUpdate ? tmpCreate : tmpUpdate); 
但您也可以选择直接分配第一个非空值,然后在tmpUpdate大于该值时覆盖该值:

lastChangedInRole = tmpCreate ?? tmpUpdate; 
if (tmpUpdate > lastChangedInRole) 
  lastChangedInRole = tmpUpdate;
(理由:如果只有一个值,则比较将始终为false,并使用
??
分配非空值,否则将分配
tmpCreated
,只需将其与
tmpUpdate
进行比较)

使用^(xor)检查是否有一个条件为true(等于null)然后返回第一个NOTNULL值。如果两者都不为null,则使用现有表达式

if (tmpCreate == null ^ tmpUpdate == null)
   lastChangedIndrole = tmpCreate ?? tmpUpdate;
else
   lastChangedIndrole = (tmpCreate > tmpUpdate ? tmpCreate : tmpUpdate); 
if(tmpCreate==null^tmpUpdate==null) lastChangedIndrole=tmpCreate??tmpUpdate; 其他的
lastChangedIndrole=(tmpCreate>tmpUpdate?tmpCreate:tmpUpdate);

为什么您希望这会引发异常?请注意,您所说的代码中没有构造函数。您是指“条件运算符”而不是“构造函数”吗?您可能还想检查值是否为
null
或等于
DateTime.MinValue
,在将操作结果分配给另一个变量(导致另一个奇怪的行为和难以调试)之前,确保数据有效是很重要的。我想您的意思是使用“构造”,而不是“构造”,因为后一个词在.NET和C#(事实上还有很多编程语言)中有特殊的含义,而“construct”是指由更小的部分组合而成的东西,或者是由术语和思想组合而成的语句/句子。我没有写完整的代码。我的问题就像:当代码检查一个可空值的值,然后
lastChangedInRole = tmpCreate ?? tmpUpdate; 
if (tmpUpdate > lastChangedInRole) 
  lastChangedInRole = tmpUpdate;