Casting' with Reflection

casting' with reflection

void SetValue(PropertyInfo info, object instance, object value)
{
info.SetValue(instance, Convert.ChangeType(value, info.PropertyType));
}

Cast to a reflected Type in C#

No :-)

Case 1:

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Foo result = (Foo)objFoo;

There is no reflection here, because you know the Foo type at compile time.

Case 2: interfaces. Normally the best one... You don't know what exactly MakeFoo returns, but you know it's an IFoo interface...

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
IFoo result = (IFoo)objFoo;

Case 3: you aren't sure MakeFoo returns Foo

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}

if (objFoo is Foo)
{
Foo result = (Foo)objFoo;
}

or, similar

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}

Foo foo = objFoo as Foo;

if (foo != null)
{
// use foo
}

Case 4: type Foo is completely unknown to your program. You don't have a Foo class referenceable...

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Type typeFoo = objFoo.GetType(); // You should check for null values before!

// and now?

dynamic foo = objFoo;

// because you know that foo can Quack(1, 2, 3)!
string result = foo.Quack(1, 2, 3);

// note that it will explode with a RuntimeBinderException if there is no
// string Quack(int, int, int) method!

the dynamic internally uses reflection. You could use reflection directly to get the Quack method and call it

Case 5: as case 4, but using directly reflection:

object objFoo = MakeFoo(); // object MakeFoo(){return new Foo();}
Type typeFoo = objFoo.GetType(); // You should check for null values before!
MethodInfo mi = type.GetMethod("Quack"); // You should check if the Quack method
// exists
string result = (string)mi.Invoke(objFoo, new object[] { 1, 2, 3 });

or, with some sanity checks, if you aren't sure foo can Quack correctly:

MethodInfo mi = type.GetMethod("Quack", 
BindingFlags.Instance | BindingFlags.Public,
null,
new[] { typeof(int), typeof(int), typeof(int) },
null);

if (mi != null && typeof(string).IsAssignableFrom(mi.ReturnType))
{
string result = (string)mi.Invoke(objFoo, new object[] { 1, 2, 3 });
}

Case -Infinity: type Foo is completely unknown to your program. You don't have a Foo class referenceable. You don't have an IFoo interface. You don't even know what a Foo is, you know only that it's a class (or perhaps it's a boxed struct, but it doesn't change from your point of view... It can't be an interface because in the end there must always be a concrete class/struct behind every interface). You don't know of its methods, its fields, its properties (because you don't know what Foo is).

Even if you can cast an object to this unknown class, what can you do? You can't have methods in your code that accept it as a parameter/return value, because if somewhere you had:

int INeedFoo(Foo par) { return 0; }

then clearly you would know of Foo. The .NET library can't have methods that accept it as a parameter/return value, because if it had, you would know of Foo.

The only thing you can do is pass it to some other methods that you discover through reflection that accept Foo as a parameter... But the Invoke method accepts an array of object as parameters... You don't need to cast your object to call Invoke! You only need to put it in the array.

Casting a class using reflection in java

You can use Generics to declare

Class<? extends A> klass;

then you'll be allowed to write

A a = klass.newInstance();

However, since Class.forName has no type information on your class, and has no type inference declared, you'll be getting "unchecked cast" warnings. This approach is no more typesafe than just downcasting the result of the second line to A.

.NET reflection cast to exact type

  • An object's type is runtime information.
  • A variable's type is compile-time information.
  • Compile-time comes before runtime.

The conclusion here is that it's not possible to have a statically typed variable that matches the exact type of an arbitrary object instance, because doing so would require information that is not available yet.

As a workaround, consider making the variable dynamic and see what you can do from there.

JAVA reflection cast object to class given by name of a specific supertype

You seem to be confused about what casting does. The cast syntax, which looks like: (Dog) someAnimal; does 3 completely unrelated things.

1) The first thing it does is type coercion, which actually converts a value from one kind to another. You get this ONLY IF the thing in the parens is primitive. Example: int x = (int) 5.5; will 'coerce' the 5.5 (which is a double) to be converted to 5 (an int).

2) The second thing it does is a type check. This is what happens where the thing in the parens is a non-primitive type, and not a type that is less specific than the expression. So, for example: Animal a = someAnimal(); Dog d = (Dog) a;. You seem to think that this operation converts an animal into a dog. It does not. All this does is typecheck: a is a variable of type Animal, and all that means is that it is either pointing at null, or pointing at some object that is either an instance of Animal (the class) itself or any subtype thereof. It is perfectly allright for 'a' to be of type Animal and be pointing at an object of type Cat (which is a subtype of Animal). Writing (Dog) a will typecheck: If a is currently pointing at either some instance of the class Dog, or null, this operation doesn't do anything at all. If it is NOT currently pointing at a dog (say, it is pointing at a cat), that expression will cause a ClassCastException to be thrown. In no case will this operation ever convert anything.


  1. The final, most esoteric use is where you do something like: Dog d = someDog(); Animal a = (Animal) d;. In most cases this is a complete no-op and your IDE will warn you that doing this is completely meaningless; just Animal a = d; is just as legal. However, the type still changes which can have an effect on which method you are calling and what lambdas will be typed to. If this is gobbledygook to you, don't worry about it; this comes up basically never.

Further confusions you appear to hold:

The only valid assignment to a variable of Class<Animal>, is Animal.class (and null). Dog.class wouldn't be allowed there. If that was your intent, the correct type is Class<? extends Animal>.

You can cast INSTANCES reflectively using the cast method of any class. For example:

Dog dog = Dog.class.cast(someAnimal());
Dog dog = (Dog) someAnimal();

are entirely equivalent: This does nothing, unless someAnimal() returns a non-dog, in which case, that will cause a ClassCastException to be thrown.

If you want to check if some class instance is compatible with animal, you can do that:

Class<?> dogClass = Dog.class;
if (!Animal.class.isAssignableFrom(dogClass)) { /* error here */ }

Alternatively there's asSubclass:

Class<? extends Animal> animalClass = Dog.class;
Class<? extends Dog> dogClass = animalClass.asSubclass(Dog.class);
assert dogClass == animalClass;

Note how the asSubclass method again doesn't do anything, it just makes javac stop complaining. At runtime generics is eliminated; it's all just Class, the bit in the <> is gone. Hence, dogClass and animalClass are 2 variables both pointing to the exact same object (namely, the j.l.Class instance representing your Dog class).

Why is casting faster than reflection in .NET?

Reflection is slow because you are querying the assembly's metadata whereas casting simply changes the type of the object you are referencing.

The assembly's metadata is a useful store of information but that information is best used at compilation time rather than at execution time. That metadata is used by the compiler for static type checking (among other things). You are using that same metadata to look up type information at execution time (which is fine if you have no other choice) which is significantly slower than casting.

Cast via reflection and use of Class.cast()

An example where is does work:

class Favorites {
private Map<Class<?>, Object> map = new HashMap<Class<?>, Object>();

public <T> T get(Class<T> clazz) {
return clazz.cast(map.get(clazz));
}

public <T> void put(Class<T> clazz, T favorite) {
map.put(clazz, favorite);
}
}

which allows you to write:

Favorites favs = new Favorites();
favs.put(String.class, "Hello");
String favoriteString = favs.get(String.class);

The reason your code doesn't work is that Class.forName() returns a Class<?>, i.e. a class object representing an unknown type. While the compiler could possibly infer the type in your example, it can not in general. Consider:

Class.forName(new BufferedReader(System.in).readLine())

what's the type of this expression? Clearly the compiler can not know what the class name will be at runtime, so it doesn't know whether

String s = Class.forName(new BufferedReader(System.in).readLine()).cast(o);

is safe. Therefore it requests an explicit cast.

How to cast implicitly on a reflected method call

Found an answer which uses a TypeConverter (as Saeed mentions)

Seems to do the job.

TypeConverter For Implicit Conversion when using reflection



Related Topics



Leave a reply



Submit