GetType and variables declared as an interface type

  • Thread starter Thread starter Bob
  • Start date Start date
B

Bob

This has been bugging me for a while now.

GetType isn't availble for variables decalred as interface types, I have to
DirectCast(somevariable, Object).

In example:

Sub SomeSub(ByVal Dictionary as IDictionary)
If Dictionary is Nothing Then Return
Dim o as Object = DirectCast(Dictionary, Object)
If GetType(ISomeInterface).IsAssignableFrom(o.GetType) Then
'<... some code...>
End If
End Sub

Does this mean that it is possible to have variable types that are not derived
from Object? And if not, why aren't all variables treated as Objects?

Bob
 
Bob said:
This has been bugging me for a while now.

GetType isn't availble for variables decalred as interface types, I
have to DirectCast(somevariable, Object).

In example:

Sub SomeSub(ByVal Dictionary as IDictionary)
If Dictionary is Nothing Then Return
Dim o as Object = DirectCast(Dictionary, Object)

You don't need Directcast here:
dim o as object = dictionary
If GetType(ISomeInterface).IsAssignableFrom(o.GetType) Then
'<... some code...>
End If
End Sub

Does this mean that it is possible to have variable types that are
not derived from Object?
No.

And if not, why aren't all variables treated
as Objects?

The Interface does not have a GetType method.
 
Bob said:
GetType isn't availble for variables decalred as interface
types, I have to DirectCast(somevariable, Object).

'DirectCast' to 'Object' doesn't make sense, because 'Object' is the more
general type.
Does this mean that it is possible to have variable types that
are not derived from Object?
No.

And if not, why aren't all variables treated as Objects?

An interface cannot be instantiated, there cannot be objects with the type
of an interface. Classes can implement interfaces and classes can get
instantiated.
 
Hi Bob,

Pardon me if this is irrelevant Bob, I'm not sure I understand the question properly so a bit of a ramble about Interfaces...

|| Sub SomeSub(ByVal Dictionary as IDictionary)

You can't just call this with any old variable - it has to be one whose class implements the given interface. In this case, for
example, a HashTable.

One of the purposes of using an interface for a method parameter is to restrict what can be done with the variable. For example,
the HashTable provides Clone, ContainsKey and ContainsValue, amongst others. These are not available to the Dictionary parameter as
they are HashTable specific.

It's perhaps clearer if you have two disparate objects, say an Elephant and a BananaBalloon (as at the seaside). Both of these
might implement an IPeopleCarrier interface with such properties as Capacity, etc.

There's no way that you could define a method which takes either an Elephant or a BananaBalloon but no other object - except by
using the interface, eg Sub LoadUp (oCarrier As IPeopleCarrier).

=================================
Having written this, and played around in VB, I wasn't happy that I was answering you, so I decided to try the same in C#.

|| GetType isn't availble for variables decalred as interface types

True, I'm afraid. Have a look at the following C# code:

static void Main()
{ HmmmInterfaces (new Hashtable()); }

static void HmmmInterfaces (IDictionary d)
{
Hashtable h = new Hashtable();
Type th = h.GetType();
Type td = d.GetType(); // Won't compile in VB. It says that
// GetType is not a member of IDictionary.
}

This is perfectly acceptable C# and, with this code, td is HashTable.
In VB you can't get call GetType on d.

So now I think I understand your question. - How are you supposed to know what you are dealing with?

Well, you're right about the DirectCast.

This will give HashTable
Dim td As Type = DirectCast(d, Object).GetType
If td Is GetType(Hashtable) Then

And TypeOf is available too.

This will be True only for HashTable
If TypeOf d Is Hashtable Then

This will be always be True (as the parameter is an IDictionary)
If TypeOf d Is IDictionary Then

|| Does this mean that it is possible to have variable types that
|| are not derived from Object?

No, I just think that while GetType is available in C#, it has, for some arbitrary (ie I can't fathom it :-)) reason, has been
removed from Interfaces in VB.


I hope this is of some use to you.

Regards,
Fergus
 
Bob,
In addition to what the others have stated.

IDictionary is an interface, in VB.NET interfaces do not gain anything from
System.Object.

Oddly enough in C# interfaces do gain the methods from System.Object. I
don't think C# views interfaces as inheriting from System.Object, as much as
it knows that any variable will have methods of System.Object available. As
you need an object (which inherits from System.Object) to implement any
Interface.

So in C# you can use GetType on a Interface variable, as Fergus
demonstrated.

Which is correctly I'm really not sure, as technically there is not a super
interface for Interfaces, such as System.Object is the super class for
Classes..

By super class & super interface I mean the most base Type that a Type
inherits from.
Does this mean that it is possible to have variable types that are not derived
from Object? And if not, why aren't all variables treated as Objects?
Yes. Remember System.Object is a class, while an Interface is an interface.
They are two distinct types of Types, very similar in many regards, but
distinct non the less.

You cannot have a Class in VB.NET inherit from an Interface, nor can you
have an Interface inherit from a Class. A Class Implements an Interface,
while an Interface can inherit other Interfaces.

Hope this helps
Jay
 
It is allowed with Option Strict On, and I have yet to see such a conversion
fail under any circumstance at runtime; if you want to assert that the code
below does not 'make sense', you must provide an example where it causes an
exception.

But I do not believe one exists, as all vairables are either nothing or not
nothing. And if a variable is not nothing, if I understand the others' comments
correctly, it must be derived from Object.

Bob
 
Bob,
I agree with Herfried, it does not 'make sense' in that the DirectCast is
100% redundant!

Dim i As ICloneable
Dim o As Object

i = o

i = DirectCast(i, Object)

Both do the same thing, yet the statement with DirectCast is 20 characters
longer. Typing 20 extra characters 'does not make sense'.

Yes its allowed, I would be very surprised if it ever caused an exception.

However! is it really needed, does it really add any value to the statement?
I don't see that its needed or adds value, hence I agree with Herfried, it
does not make sense.

Remember when casting to Object or a base type, DirectCast is not needed.
Otherwise we could not use Object as a parameter type to allow any variable
to be passed.

Just a thought
Jay
 
Suppose you are stuck with the IClonable variable, it's coming in as part of the
signature of a method. Suppose now you need to determine if some other interface
is assignable to this variable's type. How would you do this without first using
the Object type either by casting or assignment?

Bob
 
Bob,
the Object type either by casting or assignment?
This is key to what doesn't make sense is "casting OR assignment", what I am
saying does not make sense is using Casting on the Assignment to Object.

I use casting when I need casting otherwise I use simple assignment. Trust
me I need casting as I use Option Strict On!
Suppose now you need to determine if some other interface
is assignable to this variable's type.
Huh?? Wouldn't it be far more beneficial to ask a variable if it supports
some type, rather than asking a type if it supports some type? In other
words rather then use Type.IsAssignableFrom use a TypeOf Is expression
instead.

I would use 'Typof Is' expression:

Dim i As ICloneable
Dim x as whatever

If Typeof x is ICloneable Then
' do something with x,
' what I cannot tell by your statement
End If
How would you do this
Normally I would use the 'Typeof Is' expression.

Dim i As ICloneable
If TypeOf i Is IComparable Then
Dim c As IComparable
c = DirectCast(i, IComparable)
End If

Remember that IComparable has no relationship to ICloneable (more
specifically IComparable does not inherit from ICloneable) & it is not
Object, hence I need to use the DirectCast as part of the assignment.

Going back to original post:

I would use something like:

Sub SomeSub(ByVal dictionary as IDictionary)
If dictionary is Nothing Then Return
If TypeOf dictionary Is ISomeInterface Then
Dim some As ISomeInterface
some = DirectCast(dictionary, ISomeInterface)
'<... some code...>
End If
End Sub

Or if you are working with Type variables in a generic sense:

Private m_type As Type = GetType(ISomeInterface)

Sub SomeSub(ByVal Dictionary as IDictionary)
If Dictionary is Nothing Then Return
Dim o as Object = Dictionary
If m_type.IsAssignableFrom(o.GetType) Then
'<... some code...>
End If
End Sub

Notice there is no DirectCast on the assignment to Object (compiles without
it with Option Strict On)! However with the GetType(ISomeInterface) in your
original post suggests you are not using Type variables.

Hope this helps
Jay
 
Bob,
I had it in my head that it would fail under certain conditions. But now I can't
seem to find an example and you are right.
If you think of it, let me know.

Remember that TypeOf allows you to check generically derived types match a
base type. While using GetType allows you to check for a specific type
(exclusive of derived types).

Dim fs As New IO.FileStream("myfile.xml", FileMode.Open,
FileAccess.Read)
Dim isType As Boolean

' returns true, as fs is an IO.Stream & an IO.FileStream
isType = TypeOf fs Is IO.Stream

' returns false, as fs is not specifically an IO.Stream
isType = fs.GetType() is GetType(IO.Stream)

TypeOf is my first choice, however the second is handy in some isolated
cases.

Hope this helps
Jay
 
Hi Bob,

|| That's par for the course for me.

Yep - learning all the time. ;-)

Regards,
Fergus
 
Back
Top