Object.GetType - how to call correctly

  • Thread starter Thread starter Yan Vinogradov
  • Start date Start date
Y

Yan Vinogradov

Hi,

Turns out it's possible to spoof another type with Object.GetType
method. If you do this:

namespace N {
class C {
public new Type GetType() {
return (String.Empty.GetType());
}
}
}

and then somewhere in the code you do:

C c = new C();
Console.WriteLine(c.GetType())

the output will be "System.String"

Apparently the way to make it work right is to upcast the reference to
Object:

C c = new C();
Console.WriteLine(((Object)c).GetType())

will yeild "N.C"


I'd appreciate your comments on that.

Yan
 
Hi, Yan.
It's true that you can overwrite the GetType method with "new" operator,
but consider a real world use case: If you know that you have a reference to
type C, it wouldn't be necessary for you to call GetType on top of it to get
a reference to Type C. You would, instead, use typeof operator, which is
resolved at compile time. Only when you can't figure out the type at compile
type, E.g: having an object reference, would you call GetType to get its
type. So, I wouldn't worry about it.
If you want to stay at the safe side, of course, it's safer to convert it
to Object before calling GetType.

Regards
Ming Chen
 
Hi,

I see nothing weird there, GetType is a method in the same way that any
other method, you can give it a new meaning , and in such way you can trash
the original intention of the method and even give a complete different
meaning, bad code from who write it, that's all.

Why you see it weird in any way?

cheers,
 
Hi Ming Chen,

I have yet very little experience with C#, but isn't it possible that
you receive a reference to a C object that has a number of subclasses,
and this reference can be pointing to an instance of any of these
subclasses, and you call GetType() to know the actual type but get
some 'spoofed' value in return?

Thanks,
Yan
 
Yan Vinogradov said:
I have yet very little experience with C#, but isn't it possible that
you receive a reference to a C object that has a number of subclasses,
and this reference can be pointing to an instance of any of these
subclasses, and you call GetType() to know the actual type but get
some 'spoofed' value in return?

As Ming said, if you cast to object first, you'll always get the
correct version:

Type t = ((object)something).GetType();
 
Ignacio Machin ( .NET/ C# MVP ) said:
Hi,

I see nothing weird there, GetType is a method in the same way that any
other method, you can give it a new meaning , and in such way you can
trash
the original intention of the method and even give a complete different
meaning, bad code from who write it, that's all.

Why you see it weird in any way?

It's odd to me that GetType() isn't a sealed method (or non-virtual, however
you'd like to look at it.). I don't see the point in allowing it to be
overridden. Insufficient imagination, perhaps.

For comparison, Java's.Object.getClass() is final.
 
Mike Schilling said:
It's odd to me that GetType() isn't a sealed method (or non-virtual,
however you'd like to look at it.). I don't see the point in allowing it
to be overridden. Insufficient imagination, perhaps.

GetType() is non-virtual. Virtuality has no affect on being able to cover a
method with a new one, however. That method does not override GetType() it
is just a method on a descendent that happens to have the same name.

Remember, in C#, virtual has to be explicitly defined, so sealed makes no
sense being applied to the method unless it was virtual at one point.
 
Daniel O'Connell said:
GetType() is non-virtual. Virtuality has no affect on being able to cover
a method with a new one, however. That method does not override GetType()
it is just a method on a descendent that happens to have the same name.

Thanks, I was misunderstanding the issue. One of the posters upthread had
mentioned name hiding in C++; now I see that he'd described the situation
exactly. It's also clear why casting to Object resolves the issue.

So I could also define, say,

public class ConfuseCallers {
new public String GetType() { return "fooled you";}
}

and now the result of

ConfuseCallers c = new ConfuseCallers();
Type t = c.GetType();

is a compilation failure.

What a language! :-)
 
Mike Schilling said:
Thanks, I was misunderstanding the issue. One of the posters upthread had
mentioned name hiding in C++; now I see that he'd described the situation
exactly. It's also clear why casting to Object resolves the issue.

So I could also define, say,

public class ConfuseCallers {
new public String GetType() { return "fooled you";}
}

and now the result of

ConfuseCallers c = new ConfuseCallers();
Type t = c.GetType();

is a compilation failure.

Yes, you could. However, I would blacklist anything you've written,
permenantly, ;).

Its a feature thats useful to have in that <1% of cases where it makes sense
and a bit of a liability the rest of the time.
 
Back
Top