I am working on the data access in C++ ATL/COM.
How do you pass a nullable type (e.g. nullable integer) in an interface???
In ATL/C++ in in interfaces (IDL) you don't have nullable classes and support in language constructs (<type>? in C#). Nullable is basically the type itself and an extra BOOL indicating whether we currently have NULL or not.
One can implement a relatively simple template class to look - to extend possible - similarly to C# Nullable. On the interface this will be either two arguments, or as you discovered you can use VARIANT type since it already embeds payload value and .vt member indicating type. VT_NULL constant is what it says for itslef - the value of the whole variant is null.
Related
I've created 2 kotlin methods: one to check a type and another to cast an object. They look like:
fun Any?.isOfType(type: Class<*>): Boolean{
return type.isInstance(this)
// return `this is T` does NOT work.
}
and
fun <T> Any?.castToType(): T {
return this as T
// Works, albeit with a warning.
}
I've read some posts on generics and erasures, but I can't get over what seems to be a discrepancy.
Why is it that checking for the type of an object cannot be done with generics, but casting to a generic can?
The question is why:
fun <T> Any?.castToType() = this as T // compiles with warning
"hello".castToType<Int>()
"works" but this won't even compile:
fun <T> Any?.isOfType() = this is T // won't compile
"hello".isOfType<Int>()
Actually both don't really work. In both cases the type is erased at runtime. So why does one compile and the other doesn't?
this is T cannot work at runtime since the type of T is unknown and thus the compiler has to reject it.
this as T on the other hand might work:
"hello".castToType<Int>() // no runtime error but NOP
"hello".castToType<Int>().minus(1) // throws ClassCastException
2.0.castToType<Int>().minus(1) // no runtime error, returns 1
In some cases it works, in others it throws an exception. Now every unchecked cast can either succeed or lead to runtime exceptions (with or without generic types) so it makes sense to show a warning instead of a compile error.
Summary
unchecked casts with generic types are no different from unchecked casts without generic types, they are dangerous but a warning is sufficient
type checks with generic types on the other hand are impossible at runtime
Addendum
The official documentation explains type erasure and why is-checks with type arguments can't succeed at runtime:
At runtime, the instances of generic types do not hold any information about their actual type arguments. The type information is said to be erased. For example, the instances of Foo and Foo<Baz?> are erased to just Foo<*>.
Due to the type erasure, there is no general way to check whether an instance of a generic type was created with certain type arguments at runtime, and the compiler prohibits such is-checks such as ints is List or list is T (type parameter)
(https://kotlinlang.org/docs/generics.html#type-erasure)
In my own words: I can't check whether A is B if I don't know what B is. If B is a class I can check against an instance of that class (that's why type.isInstance(this) works) but if B is a generic type, the runtime has no information on it (it was erased by the compiler).
This isn't about casting vs checking; it's about using generics vs class objects.
The second example is generic; it uses T as a type parameter. Unfortunately, because generics are implemented using type erasure, this means that the type isn't available at runtime (because it has been erased, and replaced by the relevant upper bound — Any? in this case). This is why operations such as type checking or casting to a type parameter can be unsafe and give compilation warnings.
The first example, though, doesn't use a type parameter; instead, it uses a parameter which is called type, but is a Class object, representing a particular class. This is a value which is provided at runtime, just like any other method parameter, and so you can call methods such as cast() and isInstance() to handle some type issues at runtime. However, they're closely related to reflection, and have some of the same disadvantages, such as fragility, ugly code, and limited compile-time checks.
(Kotlin code often uses KClass objects instead of Java Class objects, but the principle is the same.)
It may be worth highlighting the difference between class and type, which are related but subtly different. For example, String is both a class and a type, while String? is another type derived from the same class. LinkedList is a class, but not a type (because it needs a type parameter); LinkedList<Int> is a type.
Types can of course be derived from interfaces as well as from classes, e.g. Runnable, or MutableList<Int>.
This is relevant to the question, because generics use type parameters, while Class objects represent classes.
This answer says that Object types use the null value on lateinits of Object type. Can someone elaborate on this? What do they mean by "uses the null value"?
Furthermore it says "For primitive types, there is no such value" - why is there no
On the JVM, which was historically the first platform targeted by Kotlin, there is a distinction between the primitive types and classes, or object types.
They have different runtime representations: a primitive value is stored directly in the field, which can only hold one of the corresponding primitive type values (e.g. only true and false for boolean) and has no special representation for a missing value. In comparison, a class-typed field stores an indirect reference to an instance that is allocated somewhere in the heap, and a class-typed field can hold a special null reference that doesn't point to any instance.
The Kotlin lateinit properties are compiled to a single field and they internally use the null value to indicate that the property has not yet been initialized. As primitive-typed JVM fields can't have a null value, Kotlin doesn't allow lateinit properties of types that are normally mapped to Java primitives, as that would require a different representation, and no acceptable solution existed, as the other answer says.
Instead, you can use by Delegates.notNull() to achieve similar behavior with the mapped types.
I know it's possible to defer the definition of procedures from an abstract type to its derived types. Is it possible to include 'deferred' data in an abstract type, i.e., data whose type and value is only defined in derived classes?
The closest question I found on stackoverflow was here. It does not address my needs.
If clarification is needed, please ask. Many thanks.
There's no straightforward way to defer the definition of a data component of an (abstract) derived type as there is for procedure components, so no declaration such as
type(magic), deferred :: element
which can be overridden by a concrete declaration in an extended type. I think the easy (?) workaround would be to use class in the declaration. For ultimate flexibility you could use an unlimited polymorphic component, eg
type :: stype
class(*), allocatable :: element
end type style
What you can't then do is specify the type in a concrete extended type with a (re-)declaration something like
type, extends(stype) :: mstype
integer :: element
end type mstype
Instead, if you want to define an extended type which has an integer element you would create the type and write a constructor for it that ensures its element is allocated with type integer.
If your requirements are more modest the 2003 feature of parameterised derived types might satisfy you, but as far as I know only the Cray and IBM XL compilers implement that yet.
I've come from a Assembler and C/C++ background, so I understand the concept behind reference types versus value types in vb.net. Also, I've read Jon Skeet's article regarding references and value types and I understand all of that.
My question is: How can you tell if a given type is a reference type or a value type?
Is it simply that all integral types (ints, floats, etc.) are value types and all classes are reference types? (If so, where do strings fall?)
Question 2 (related): Is there a way to declare a class as a value class versus a reference class? For example (using extreme brevity):
Public Class MyClass1
Public Value As Integer
End Class
Using this class:
Dim test1 As New MyClass1
test1.Value = 1
Dim test2 As MyClass1
test2 = test1
test2.Value = 2
At the end of this code, the Value in Test1 is 2. Clearly, MyClass1 is a reference type. But, what is it that causes it to be such and not a value type?
In general - enums and structs are value types, classes interfaces and delegates are reference types.
As for declaring a class as a value type - this is not possible, but C# structs are very close to classes and are value types.
As for VB.NET, I believe the equivalent is the Structure statement:
The Structure statement defines a composite value type that you can customize.
In the code base I'm working in there have a method that has the signature
Public Sub SetDropDownValue(Of T As Structure)(ByVal target As ListControl, ByVal value As Nullable(Of T))
The method I am writing is passed a parameter of type object.
How can I cast the object into something that can be passed into the SetDropDownValue method?
No, you won't be able to cast a reference type as a value type (which is what the Structure constraint signified). The CLR does allow you to cast a value type as a reference type (this is known as boxing) but the nature of the difference between the implementation (and semantics) of these two different types makes the reverse impossible.
The only think you could do would be to create a value type that held a reference to your object as a field, but perhaps this problem may be a hint that you are going about the whole thing in the wrong way.
This should work if you know T:
something.SetDropDownValue(target, DirectCast(value, Nullable(Of T)))
See this article for details.
If you don't know the type T, you're in trouble and would have to start futzing around with reflection at runtime. This is complex, dangerous, and has awful performance.