简体   繁体   中英

How can Nullable<T> use it's underlying value type extension method

One hour ago I asked a question: how can I write an extension method for Enum?-Nullable<Enum>
surprisingly I got an answer telling me I can write the extension method for Enum and it can be used for all enums and nullable enums.

Cool, it workes, but how?

If I understand correctly, all enums derive from Enum so this why I can use this extension method in every enum I have.

But... the ItemType? enum, for example, isn't an enum, it's Nullable<ItemType> , which doesn't derives from ItemType nor Enum .
Just like List<DataReader> doesn't derive from DataReader and thus can't use DataReader methods, though DataReader is it's Generic type .

I know The Nullable<T> type has a lot of "voodoo" and syntactic sugar, is this one of them?

Extension methods do not require the class to be /derived/, they just require a conversion to exist (more specifically: an implicit identity, reference or boxing conversion; this is §7.6.5.2 "Extension method invocations").

The conversion from Nullable<ItemType> to System.Enum is a boxing conversion; same as a conversion from Nullable<int> to System.Object .

And if you defined your own structure struct Test : IMyInterface {} , there would be a conversion from Nullable<Test> to IMyInterface .

Boxing conversions from nullables will return a null reference if the nullable was null; and box the nullable's value otherwise. For details see §6.1.7 "Boxing conversions" in the C# specification.

It's more type system magic than compiler magic. Since Enum is a reference type this means that any value you pass in will get boxed (eg converted to a reference).

Now Nullable<T> has the special handling in the CLR that boxing it will yield wither null if it represents a null value or a boxed value of the inner type ( T ), but never a boxed Nullable<T> . Of course, the opposite is true as well; unboxing to a nullable type accepts a null reference.

The extension method is translated to a static method for which the first argument is the variable on which the method was invoked.

In the Enum example, since Enum is a class (not a struct), then the extension method can accept either a concrete value of the enum (which usually is boiled down to an int), or null. therefore it works with nullable enums.

that same thing would not work for int? (Nullable). if you create an extension method for int, you would not be able to invoke it on a Nullable (it will tell you "cannot convert instance argument type Nullable to int)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM