Why does variance in .NET 4 only support reference types? - .net-4.0

.NET 4 supports co- and contravariance. However, only reference types are supported, not value types. Why is that?

Basically the CLR needs to know that it can treat a value of the "source" type as a value of the "target" type without performing any extra conversions - to put it simply, the bit pattern for the source value has to be valid as the target value. The representations have to be the same. Otherwise the CLR would need to have extra information to perform the right conversions at the right time.
Eric Lippert has blogged about representation and identity - see that post for more information (as ever :).

Jon is right; to just expand on that a bit. Suppose you have
Func<int> f1 = ()=>2;
Func<object> f2 = f1;
object o1 = f1();
object o2 = f2();
Suppose that were legal. The compiler generates a boxing instruction; the third line is effectively:
object o1 = BoxIntegerToObject(f1());
Clearly the result stored in o2 should be a boxed int. Where is the boxing instruction? It cannot be after the call to f2, because that thing is guaranteed to return an object already. It cannot be in the call to f2, because the call to f2 is actually a call to f1, and f1 guarantees that it returns an unboxed int.
So the boxing instruction cannot happen after the call returns, and it cannot happen before the call returns, and therefore it cannot happen at all, and therefore this must be illegal. There is no reference conversion from Func<int> to Func<object>.

Both forms of variance are defined in terms of inheritance: value types aren't inherited.

Related

Kotlin: At which situations does implicit conversion happen?

I am a beginner in Kotlin.
I'm most familiar with Python, and I just read through the basic Java Tutorial https://docs.oracle.com/javase/tutorial/java/index.html before jumping into Kotlin.
A question came up in my mind while reading this section of the documentation of Kotlin
https://kotlinlang.org/docs/reference/basic-types.html#explicit-conversions
What I have understood from above section of the documentation is:
For assignments =, implicit type conversion happens. If the lefthand side's type is a supertype or same type of righthand side's type the code would compile. Otherwise it's a compile error. In case of Int and Long, they are both subtypes of Number but neither of them subtypes of each other, so the implicit conversion would not work. Therefore we need to use methods like .toLong() or .toInt() to explicitly convert them.
Then when I read the part
val l = 1L + 3 // Long + Int => Long
I started wondering if implicit type conversion would be taking place in this situation.
The documentation says this has to do with the operator overloading.
How is this operator overloading implemented under the hood?
I tried to find the source code at Github https://github.com/JetBrains/kotlin/blob/master/core/builtins/native/kotlin/Primitives.kt ,
but here the functions are only declared but not implemented. Where can I find the implementations?
It seems that operation overloading does not actually perform type conversion. Do we just implementing all possible functions with same name but different parameter type signatures, so that the type is inferred, then the function with the matching signature is selected?
And the general question: In Kotlin, exactly at which situations does implicit conversion happen?
For assignments =, implicit type conversion happens. If the lefthand side's type is a supertype or same type of righthand side's type the code would compile.
Assignments aren't special in this. More generally, if the expected type of an expression is a supertype or the same as actual type, the code compiles; it's just that the expected type for the right-hand side of an assignment is the left-hand side's type. I wouldn't say there is an implicit conversion inserted, but I don't think anything breaks if you see it that way.
Do we just implementing all possible functions with same name but different parameter type signatures, so that the type is inferred, then the function with the matching signature is selected?
Yes, exactly (for this case). If you want to support primitive types, you need to provide overloads for all of them.
So 1L + 3 is just a method call so far as the parsing and type-checking is concerned (`Long.plus(Int): Long specifically), no implicit conversion is involved. But these methods are built into the compiler to handle specially which is why you don't see an implementation.
It becomes two bytecode instructions i2l ("convert an int into a long") and ladd ("add two longs"), but that's not something you should probably care about yet, or for a long time.
And the general question: In Kotlin, exactly at which situations does implicit conversion happen?
Smart casts are the closest Kotlin has to implicit conversions but they are sufficiently different from i.c.s in other languages that I wouldn't use the name. So I'd say never.

Primitve Boxing StackManipulation

There seems to be a difference in the implementation of PrimitiveBoxingDelegate and PrimitiveUnboxingDelegate.
Basically I would like to box a primitive value on the stack, so it can be returned as a reference (ie. the method returns Object)
PrimitiveUnboxingDelegate.forPrimitive() provides me with a StackManipulation but unfortunately PrimitiveBoxingDelegate.forPrimitive() does not.
Is there an easy way to create a boxing StackManipulation?
You can, you just need to specify the type to which the value should be boxed to what is implicit for unboxing:
StackManipulation sm = PrimitiveBoxingDelegate
.forPrimitive(...)
.assignBoxedTo(..., Assigner.DEFAULT, Assigner.Typing.STATIC);
You can cast an int to for example a Object or a Number. You can however create illegal combinations as well what is sometimes necessary for Byte Buddy's own purposes.

Implicit Interface casts of Nullables

With VB's Option Strict On, why does a Nullable(Of T) not require an explicit cast to an interface of T when it does require one to T?
I.e.
Dim x As Integer? = 5
Dim y As Integer
Dim z As IComparable
y = x ' Fails to compile with error
' "Option Strict On disallows implicit conversions from 'Integer?' to 'Integer'."
z = x ' Succeeds
EDIT: As (sort of) shown by #SSS, part of the answer is that Nullable values are, well, nullable, and can be Nothing, which is fine for a reference like an interface. So this conversion will always succeed, unlike the conversion to T case (which fails when the Nullable has no value), and so it can be seen as an implicit conversion.
My question now becomes "how?". How is the conversion from a Nullable(Of T) (which has no interfaces of its own) to an interface of T theoretically negotiated?
I know the implementation is box Nullable<T>, which effectively strips the Nullable wrapper, but I'm confirming the concept here...
(So I'll review the documentation and see if they explain this.)
I don't see the problem?
y = x
can fail because x could hold a value of Nothing, but y is not allowed to hold a value of Nothing. The IComparable interface allows Integers to be compared to Nothing however, so that assignment is fine.
Notice that if you swap it round:
x = y
then this succeeds because every value of y can be assigned to x.
You can confirm that Integers can be compared to Nothing as follows:
MsgBox(5.CompareTo(Nothing))
From what I can tell in vb.net, the statement interfaceVariable = nullableVariable is essentially equivalent to interfaceVariable = if(nullableVariable.HasValue, CType(nullableVariable.Value, interfaceType), Nothing). The C# compiler seems to handle things the same way: interfaceVariable = nullableVariable; becomes interfaceVariable = nullableVariable.HasValue ? (interfaceType)nullableVariable.Value : null;.
If the type of nullableValue.Value implements the interface, then nullableVariable.Value will either perform return a value-type result or throw an exception. Since there exists a guaranteed boxing conversion from the return value to the interface, the cast will be legal. The only way the above code could fail would be if the nullable variable gets written between the calls to HasValue and Value, such HasValue sees the variable as non-null, but Value sees it as null and throws an exception. I believe that writing interfaceVariable = nullableVariable just tests nullity once, so that an exception could not occur; instead, an indeterminate value would get boxed.
Without actually reading documentation yet, I'm going to attempt an answer:
Firstly, the higher-level answer is that casting a Nullable to an interface is "safe" and will not throw, so it is logically a Widening operator and should not need to be explicit (compared to casting to T, when .HasValue is False it throws, so it should not be implicit with Option Strict On).
However, technically the "how" is a bit obscure: Even though some of the behaviour of Nullable is encoded in the metadata available via reflection, much of its "magic" is hidden in:
the runtime behaviour of box on a Nullable (and thus the compiler knows when to leave "lifting" to that), and
the other points made by Eric Lippert in his answer for C# and their equivalent in VB.NET.
It looks like S. Somasegar's blog post announcing changes to Nullable support in a late beta release for VS2k5 is also relevant here.

VB.Net code optimization?

I would like to ask humbly to those vb.net experts out there regarding optimization of the code. My example here is
a.
Dim lblEventCategory = CType(Me.gvSpecialEvent.Rows(e.NewEditIndex).FindControl("lblEventCategory"), Label)
b.
Dim lblEventCategory As Label = CType(Me.gvSpecialEvent.Rows(e.NewEditIndex).FindControl("lblEventCategory"), Label)
Which of the two is more efficient is it letter A? or letter B?
Can somebody help me understand these codes?
Thanks in advance
if we are talking .Net 3.5 than what 1800 INFORMATION says is not true since type inference will take place and the compiler will infer the type and hence be typesafe.
so in .Net 3.5 a and B are the same.
In Visual studio 2008 just turn Option Infer On or Off to see the difference.
Before .Net 3.5 no type inference will take place and it will use the variant type or rather the object type.
So in pre.Net 3.5 A and B are not the same.
In .NET 3.5 Dim x = value is the same as C# var x = value; The compiler will infer the type so both are equal at runtime.
The first one defines the variable lblEventCategory as a Variant type. This is generally worse than the second where you use an explicit type. The Variant type is a kind of "catch all" that can safely hold any type of variable, but you lose any and all type safety and warnings that the compiler might have been able to give you. Also a Variant type uses more memory and will be slower at run time because of the conversions that need to be performed on it.
Additionally, method calls will be "late bound" - this means that the calls to those methods will not be resolved until runtime, when the type of the variable is known, the call is then made by name. This is typically astronomically slower than if you use the explicit type where the call can be made "early bound" (i.e., at compile time).
On the other hand, Variant types do have their place. They are useful in OLE automation (COM) programming, if you are interacting with a language like VBScript that only supports variant types. In that situation, you may be wise to wrap the calls into the late-bound code so that the Variant type is converted to and from the correct type at the boundary of the call.

Does static typing mean that you have to cast a variable if you want to change its type?

Are there any other ways of changing a variable's type in a statically typed language like Java and C++, except 'casting'?
I'm trying to figure out what the main difference is in practical terms between dynamic and static typing and keep finding very academic definitions. I'm wondering what it means in terms of what my code looks like.
Make sure you don't get static vs. dynamic typing confused with strong vs. weak typing.
Static typing: Each variable, method parameter, return type etc. has a type known at compile time, either declared or inferred.
Dynamic typing: types are ignored/don't exist at compile time
Strong typing: each object at runtime has a specific type, and you can only perform those operations on it that are defined for that type.
Weak typing: runtime objects either don't have an explicit type, or the system attempts to automatically convert types wherever necessary.
These two opposites can be combined freely:
Java is statically and strongly typed
C is statically and weakly typed (pointer arithmetics!)
Ruby is dynamically and strongly typed
JavaScript is dynamically and weakly typed
Genrally, static typing means that a lot of errors are caught by the compiler which are runtime errors in a dynamically typed language - but it also means that you spend a lot of time worrying about types, in many cases unnecessarily (see interfaces vs. duck typing).
Strong typing means that any conversion between types must be explicit, either through a cast or through the use of conversion methods (e.g. parsing a string into an integer). This means more typing work, but has the advantage of keeping you in control of things, whereas weak typing often results in confusion when the system does some obscure implicit conversion that leaves you with a completely wrong variable value that causes havoc ten method calls down the line.
In C++/Java you can't change the type of a variable.
Static typing: A variable has one type assigned at compile type and that does not change.
Dynamic typing: A variable's type can change while runtime, e.g. in JavaScript:
js> x="5" <-- String
5
js> x=x*5 <-- Int
25
The main difference is that in dynamically typed languages you don't know until you go to use a method at runtime whether that method exists. In statically typed languages the check is made at compile time and the compilation fails if the method doesn't exist.
I'm wondering what it means in terms of what my code looks like.
The type system does not necessarily have any impact on what code looks like, e.g. languages with static typing, type inference and implicit conversion (like Scala for instance) look a lot like dynamically typed languages. See also: What To Know Before Debating Type Systems.
You don't need explicit casting. In many cases implicit casting works.
For example:
int i = 42;
float f = i; // f ~= 42.0
int b = f; // i == 42
class Base {
};
class Subclass : public Base {
};
Subclass *subclass = new Subclass();
Base *base = subclass; // Legal
Subclass *s = dynamic_cast<Subclass *>(base); // == subclass. Performs type checking. If base isn't a Subclass, NULL is returned instead. (This is type-safe explicit casting.)
You cannot, however, change the type of a variable. You can use unions in C++, though, to achieve some sort of dynamic typing.
Lets look at Java for he staitically typed language and JavaScript for the dynamc. In Java, for objects, the variable is a reference to an object. The object has a runtime type and the reference has a type. The type of the reference must be the type of the runtime object or one of its ancestors. This is how polymorphism works. You have to cast to go up the hierarchy of the reference type, but not down. The compiler ensures that these conditions are met. In a language like JavaScript, your variable is just that, a variable. You can have it point to whatever object you want, and you don't know the type of it until you check.
For conversions, though, there are lots of methods like toInteger and toFloat in Java to do a conversion and generate an object of a new type with the same relative value. In JavaScript there are also conversion methods, but they generate new objects too.
Your code should actally not look very much different, regardless if you are using a staticly typed language or not. Just because you can change the data type of a variable in a dynamically typed language, doesn't mean that it is a good idea to do so.
In VBScript, for example, hungarian notation is often used to specify the preferred data type of a variable. That way you can easily spot if the code is mixing types. (This was not the original use of hungarian notation, but it's pretty useful.)
By keeping to the same data type, you avoid situations where it's hard to tell what the code actually does, and situations where the code simply doesn't work properly. For example:
Dim id
id = Request.QueryString("id") ' this variable is now a string
If id = "42" Then
id = 142 ' sometimes turned into a number
End If
If id > 100 Then ' will not work properly for strings
Using hungarian notation you can spot code that is mixing types, like:
lngId = Request.QueryString("id") ' putting a string in a numeric variable
strId = 42 ' putting a number in a string variable