Dynamic casting - c#

Why do the two last lines not work and give me
The type or namespace name 'myType' could not be found
Type myType = this.GetType();
bool test = obj is myType;
var p = (myType)obj;

You need to do:
bool test = myType.IsInstanceOfType(obj);
or
bool test = myType.IsAssignableFrom(obj.GetType());
// var p = Convert.ChangeType(obj, myType); - update: this is not what the OP asked
For the second one, you can't "cast" an expression to a type which is not known at compile time. The point of casting is to reference the members of that type natively. If you don't know what the type is at compile type (because you are using .GetType()), then there is no point casting, and indeed it's impossible.

C# is a statically typed language, which means types must be known at compile time. The var keyword just means "Figure out what this type should be automatically (through inference) at compile time".
Any cast or type-check has to be against a static type. You are actually trying to use an instance of an object of type Type that describes a type. That instance is provided to you by .NET Reflection.
Once you are working with an object of a type derived at runtime you have to use reflection for all operations on that instance. For example, you can do something like this:
bool test = myType.IsInstanceOfType(obj);
bool test = typeof(obj).IsAssignableFrom(myType); // Good for checking if a type implements an interface
For your second line, you can use an object reference to hold any type:
object p = obj;

The type of object being cast to must be determined at compile time in C#. You're trying to make a cast based on the runtime type of the object which is incompatible with this notion. Hence you get this error.
Can you give us an example of what you want to do with p? There is likely a cleaner way.

If you want to know if an object is an instance or implementation of a Type at runtime, you need to do:
Type thisType = this.GetType();
Type objType = obj.GetType();
if(objType.IsAssignableFrom(type))
{
// do your stuff
}
From there, there is no way to cast an object to a runtime type since the compiler need that information at compile time. However, if you are using C# 4, you can use the dynamic type.
Type thisType = this.GetType();
Type objType = obj.GetType();
if(objType.IsAssignableFrom(type))
{
dynamic dynObj = obj;
dynObj.CallWhateverIWant();
}
However, looking at your code, there is obviously a better way to do want you want to do. Maybe you could implement some kind of interface, common to both classes and use functions from that interface at compile time.

I don't have a Visual Studio ready at the moment and this isn't something I need to do often, but for the second line I think it should look like this:
bool test = obj is typeof(this);
The third line is not possible unless you have a limited set of possible types you can switch on.

the is operator works on classes, not objects of type Type
If you want to do this sort of thing, use the dynamic keyword
http://msdn.microsoft.com/en-us/library/dd264736.aspx

Related

How to type cast in C# having needed type as System.Type

I need to initialize an instance of System.Collections.Generic.List<String> using Reflection. For example, the type name has been loaded from XML, and it is unknown before the program has launched. I got the type and its assembly:
Type T = Type.GetType("System.Collections.Generic.List`1[System.String]");
Assembly ass = T.Assembly;
After this I need to initialize my variable, but I don't want to write the type explicitly, so using:
var lst = ass.CreateInstance(T.FullName) as List<String>;
is inapropriate. I have already got the required type in T, so if I can do something like:
var lst = ass.CreateInstance(T.FullName) as T;
it should be fine. But I can't.
What do I have to do?
It's not possible to declare a variable of a 'variable' type. Any variable/property/method/parameter/class/whatever MUST be know beforehand, at compile-time, since C# is a strongly- typed language.
The only real way to deal with dynamically generated data types like in your example is to stay with the type-unsafe object or dynamic, which can contain anything, even unknown at compile-time.
Also remember that the varsyntax isn't anything variable really, it's just syntax sugar for avoiding writing the real type, which is obtained from the type on the right side of the =, so it's really of no help for your purpose.

Using a type in linq

I have a large number of classes.
From this list I get a specified type
Type aType = Type.GetType(...);
Now I want to use this type in a linq statement like:
var aResult = from obj in scope.Extent<aType>() select obj;
This does not seem to be possible, as Extent does not accept Type.
Is there any way now (with .net 4.5) to call the statement?
All I want to do is to say use Type as class. Don't invoke the class, only get with linq all objects of this type from a scope.
You can't use an instance of Type as a generic type argument - not at compile time, anyway.
If you want objects of a specific type, you could do
var aResult = from obj in scope where obj.GetType() == aType select obj;
Note that this requires an exact type match, rather than any kind of "can be assigned to" relationship.
Also note that this will only get you a series of objects - again there's no compile-time way to cast things to an instance of Type.

How can a dynamic be used as a generic?

How can I use a dynamic as a generic?
This
var x = something not strongly typed;
callFunction<x>();
and this
dynamic x = something not strongly typed;
callFunction<x>();
both produce this error
Error 1 The type or namespace name 'x'
could not be found (are you missing a using directive or an assembly reference?)
What can I do to x to make it legitimate enough to be used in <x>?
You could use type inference to sort of trampoline the call:
dynamic x = something not strongly typed;
CallFunctionWithInference(x);
...
static void CallFunctionWithInference<T>(T ignored)
{
CallFunction<T>();
}
static void CallFunction<T>()
{
// This is the method we really wanted to call
}
This will determine the type argument at execution time based on the execution-time type of the value of x, using the same kind of type inference it would use if x had that as its compile-time type. The parameter is only present to make type inference work.
Note that unlike Darin, I believe this is a useful technique - in exactly the same situations where pre-dynamic you'd end up calling the generic method with reflection. You can make this one part of the code dynamic, but keep the rest of the code (from the generic type on downwards) type-safe. It allows one step to be dynamic - just the single bit where you don't know the type.
It's hard to tell what exactly are you trying to do. But if you want to call a generic method with a type parameter that is the same as some object, you can't do that directly. But you can write another method that takes your object as a parameter, let the dynamic infer the type and then call the method you want:
void HelperMethod<T>(T obj)
{
CallFunction<T>();
}
…
dynamic x = …;
HelperMethod(x);
You can't. The whole point of generics is compile-time safety which means that they must be known at compile-time. And the whole point of dynamics is that you don't need to know the exact type at compile time and use runtime dispatching => it's the absolutely exact opposite of generics. So don't waste your time => once you get the dynamic/reflection path you can forget about generics and compile-time safety. You will have to walk that path till the end.
So to answer your question:
What can I do to x to make it legitimate enough to be used in ?
The only thing you could do is to use a type that is known at compile-time, otherwise you cannot use generics.
You get that error because x is not a type. You need to specify a type as a type parameter.
In fact, you can use dynamic as a type parameter if you use it correctly:
var dict = new Dictionary<string, dynamic>();
dict.Add("Item1", 123);
dict.Add("Item2", "Blah");
This compiles and runs just fine.
The quickest way to make this work is to make your anonymous type a real type.
So instead of
var x = new { Value = "somevalue", Text = "sometext" };
You need to do
class MyClass
{
string Text, Value;
}
....
var x = new MyClass() { Value = "somevalue", Text = "sometext" };
//this should work now
callFunction<MyClass>(x);
You should be able to call the function like this
callFunction<dynamic>();
If your function is defined as
public void callFunction<T>(T arg) {
...
}
You can simply call it with
callFunction(x);
C# is able to infer generic type parameters in many situations.

In what context is it good to use the typeof operator?

I don't understand when to use the typeof() operator? In what context is it good to use it?
It is like .GetType() except it works on a type name instead of an instance.
You would use typeof(MyType) if you need to get an instance of System.Type and you know the type at compile time. You don't need an instance of that type for resolve the description of that type (System.Type).
Eg if you had an instance you would:
object o = new MyType();
Type type = o.GetType()
But you could:
Type type = typeof(MyType)
It gets you an instance of Type from a type.
I can get the assembly of which this class is in.
typeof(MyClass).Assembly
It is also used during .Net remoting when both Marshalling an object and also getting an object from an Activator.
When Marshalling an object you need to specify the interface the object exposes that you wish to marshal...
_pServerFileXFer = RemotingServices.Marshal(m_serverFileXFer, m_strURI, typeof(IServer));
And when getting an object from the remoting services...you need to specify what type of object you want to get:
IServer server = Activator.GetObject(typeof(IServer), m_txtURI.Text) as IServer;

Why can't I use a "Type" to create a new variable in C#?

int number = 5;
Type dynamicType = number.GetType(); // dynamic type is "int"
dynamicType x = (number as dynamicType);
How would you expect the compiler to treat the variable x later in the code? It wouldn't know anything about it... so it couldn't resolve any method calls etc.
Basically what you're after is dynamic typing which is supported in C# 4 with the "dynamic" pseudo-type:
int number = 5;
dynamic d = number;
// Calls to d are resolved at execution time, so this compiles:
d.ThisWillThrowAtExecutionTime();
Type is an object that represents information about a type. It's not a designator for a variable saying it is of that type.
SomeObject myObject = new SomeObject();
Type t = myObject.GetType();
SomeObject myOtherObject = (SomeObject)Activator.CreateInstance(t);
The ability to do this goes all the way back to .Net v1.0. No need for fancy dynamic typing or anything like that.
Constructing objects with more complex constructors takes a bit more work, but it's the same idea.
You can, just not directly. You can use reflection. Basically you get the fully qualified name of the type (from the Type object) and then call CreateInstance method from an assembly object that contains that type. It should be quite simple to get the assembly reference of the current instance...
I think the Assembly.GetExecutingAssembly() method will do it.
I've written a little about this quite some time ago in a post at: http://frater.wordpress.com/2007/06/24/instantiating-classes-through-reflection-using-c-dynamic-object-creation/
That might help you out some more, though the focus was also on compiling of c# code from within a c# program, to allow for the use of C# as a scripting language, so some of the details might not be completely relevant.
Hope that helps!
Because it wouldn't make any sense.
What would you do next?
The purpose of a cast is to assign the casted object to a variable of the type that you casted it to. In this case, you wouldn't be able to do that, since a field must have a static type at compile time.
What are you trying to do?
dynamicType is an object of type "Type" that holds the Type meta-data information of type "int" hence dynamicType is and instance or object and not a qualified type so you cannot perform instantiation on that.
So, AFAIK you can't use the Type to instantiate 'basic' data types such as int.
You could use it to create objects though:
Object x=Activator.CreateInstance(dynamicType)
The issue is, if you want to call methods or access fields on a dynamic type, you have to use reflection. See the Type class documentation for instructions.

Categories

Resources