Is there a difference between a ternary operator and an if statement in C#? [duplicate]

孤者浪人 提交于 2019-12-06 06:28:57

问题


I'm working with a nullable DateTime object and ran into some strange behavior. Here's a sample function:

    public DateTime? Weird()
    {
        DateTime check = DateTime.Now;
        DateTime? dt;
        if (check == DateTime.MinValue)
            dt = null;
        else
            dt = Viewer.ActiveThroughUTC.ToLocalTime();

        //this line give a compile error
        dt = (check == DateTime.MinValue) ? (null) : (Viewer.ActiveThroughUTC.ToLocalTime());
        return dt;
    }

As far as I know, the line with the ternary operator should be the same as the preceding four lines, but VS2010 is giving me a compile error, saying that no conversion exists between <null> and DateTime (even though the object in question is a 'DateTime?'). Is there something I should know about the ternary operator or is this (gasp?) a bug?


回答1:


Both elements in the ?: operator should be of the same type (but don't have to be - see the details below). Cast null to DateTime?:

dt = (check == DateTime.MinValue) ? (DateTime?)null : ...

From the spec:

The second and third operands of the ?: operator control the type of the conditional expression. Let X and Y be the types of the second and third operands. Then,

If X and Y are the same type, then this is the type of the conditional expression.

  • Otherwise, if an implicit conversion (Section 6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.
  • Otherwise, if an implicit conversion (Section 6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
  • Otherwise, no expression type can be determined, and a compile-time error occurs.

(Interestingly, it's not actually called the "ternary" operator. It's one possible ternary (three-valued) operator, and I'm not aware of any others in C#. It's called the "?:" operator, which is a little hard to pronounce. Also called the "conditional" operator.)




回答2:


Several answers have incorrectly stated that both values of the conditional operator must be the same type. This is decidedly untrue and is covered in detail in section 7.13 of the language spec

From the spec (X and Y are the types of the two values)

  • If X and Y are the same type, then this is the type of the conditional expression.
  • Otherwise, if an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.
  • Otherwise, if an implicit conversion (§6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression.
  • Otherwise, no expression type can be determined, and a compile-time error occurs.

The second and third cases allow for the types to be different so long as there is an implicit conversion from one to the other (but not back).

The easiest way to fix this scenario is to explicitly cast one of the operands to DateTime?

DateTime? dt = (check == DateTime.MinValue) 
  ? (DateTime?)null
  : Viewer.ActiveThroughUTC.ToLocalTime();



回答3:


Using the ternery operator the arguments have to be the same type. Change it to:

dt = (check == DateTime.MinValue) ? (DateTime?)null : 
        (DateTime?)Viewer.ActiveThroughUTC.ToLocalTime();   

the cast on the second argument (the real dateime) may not be necessary as there is an implicit cast fropm DateTime to DateTime?, and the first cast (DateTime?)null tells the compiler what to cast it to...




回答4:


Use new DateTime?() instread of null. That way it knows what type the expression is supposed to be.

dt = check == DateTime.MinValue ? new DateTime?() : DateTime.Now;



回答5:


A conditional statement's return options must be of the same type (or only one most be implicitly convertable), the implicit conversion to the nullable that the compiler infers with:

dt = null;

Doesn't happen here (if they differ should the first be converted to the second? or vice-versa?), so your return types from each option need to match or be convertable. For example this would work:

dt = check == DateTime.MinValue ? (DateTime?)null : Viewer.ActiveThroughUTC.ToLocalTime();


来源:https://stackoverflow.com/questions/3877773/is-there-a-difference-between-a-ternary-operator-and-an-if-statement-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!