Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C# implicitly convert to nullable DateTime if there is no implicit operator for nullable DateTime?

Tags:

c#

This is a question about the C# language or at least how that language is implemented in Visual Studio.

Assume one has a class Foo which defines an implicit operator to System.DateTime

public static implicit operator DateTime(Foo item)

Consider the following code:

Foo foo = SomeMethodWhichCanReturnNull();    
DateTime?  dtFoo = foo;

What I would expect: A failure-to-compile complaining that there is no conversion from Foo to DateTime?.

What I find: The compiler actually calls the defined implicit operator from Foo to DateTime and crashes when it is passed a null (which is the only way the converter can respond to a null).

Of course, work-around is to define

public static implicit operator DateTime?(Foo item)

but why do I have to do this? Are not DateTime and DateTime? two different types?

like image 227
Tevya Avatar asked May 31 '13 17:05

Tevya


People also ask

What does %C mean in C programming?

While it's an integer, the %c interprets its numeric value as a character value for display. For instance for the character a: If you used %d you'd get an integer, e.g., 97, the internal representation of the character a using %c to display the character ' a ' itself (if using ASCII)

Why do we need a C in a sentence?

So why do we need a C? When we combine the C with an H we DO make a unique sound. Without a C we would go to Hurch instead of Church, we would listen to a Hime instead of a Chime, etc. So the C is indeed a very important letter and has no reason to feel ashamed because it makes no sound on it own.

Why learning C programming is a must?

Why learning C Programming is a must? C is a procedural programming language. It was initially developed by Dennis Ritchie between 1969 and 1973. It was mainly developed as a system programming language to write operating system.

Why do drives start from c?

Why Not A Or B? Why Do Drives Start From C? The various logical drives in Windows are assigned a drive letter. Generally, the drive letter for the first logical drive is C followed by D, E, F. Well, A and B are also alphabets but Windows reserves these drive letters for some special purpose, which is floppy drives.


2 Answers

First off, the C# language specification says that a built-in implicit conversion can be inserted on either side of a user-defined implicit conversion. So if you had a user-defined implicit conversion from Shape to Giraffe then you are automatically allowed to convert from Square to Mammal, because it goes Square --> Shape --> Giraffe --> Mammal. In your case the extra conversion is only inserted on one side, presuming that the operand is of type Foo. There is an implicit conversion from any type to its corresponding nullable type. A second user defined conversion is never inserted; only built in conversions can be inserted on either side.

(I note that this is true of user-defined explicit conversions as well; explicit conversions may be inserted on either side.)

Second, you are in violation of the specification, which strongly suggests that a user-defined implicit conversion should never throw an exception. If you cannot guarantee that the operation will succeed then either change the types or make it an explicit conversion.

Third, you might be interested to know that the C# compiler will automatically define a "lifted" conversion if both types in a user-defined implicit conversion are non-nullable value types. If you have a user-defined implicit conversion from struct type S to struct type T then you get a "lifted" conversion from S? to T? for free, with the semantics of s.HasValue ? new T?((T)s.Value) : new T?().

This subject is one of the more complex areas in the C# specification so I recommend that you read it carefully if you wish to know the exact details.

like image 64
Eric Lippert Avatar answered Sep 28 '22 03:09

Eric Lippert


DateTime? is actually a C# syntactic sugar to represent Nullable<DateTime>. When you write something like DateTime? dtFoo = foo the compiler actually generate code like:

Nullable<DateTime> dtFoo = new Nullable<DateTime>(foo);

Which is perfectly fine from compiler point of view as the nullable constructor take a DateTime as param and foo has type conversion for it.

like image 34
Ankur Avatar answered Sep 28 '22 03:09

Ankur