Why is C# dynamic type static? - c#

While reading and exploring the dynamic keyword I found following line on [MSDN] (in Using Type dynamic (C# Programming Guide)):
The type is a static type, but an object of type dynamic bypasses static type checking. In most cases, it functions like it has type object.
What is the meaning of static in above line and how does it bypass static type checking?

This is static typing:
string foo = "bar";
foo is now a string, so this will cause a compile time error:
foo = 1;
Even if you use var, it's still statically typed:
var foo = "bar"; // foo is now a string
foo = 1; // still a compile time error
Using the dynamic keyword, means the type won't be static and can be changed, so now you can do this:
dynamic foo = "bar";
foo = 1; // this is now fine.
Now, why it says "the type is a static type" is because in many dynamic languages (like Javascript), you can do something like this:
var foo = { bar: 1 };
Which creates an object with a property called "bar", and then you can do this:
foo.la = 2;
Which adds a new property to the object in foo. But if you try the same trick in C#
dynamic foo = new SomeClassThatDoesntHaveABarProperty();
foo.bar = 2; // runtime error
Nor can you delete a property. You can assign any type to a dynamic variable, but you can't change those types themselves.
If you do need that type of functionality, then you'll want to look at ExpandoObject
As your description says, dynamic functions like an object in a lot of cases. You could do this:
dynamic foo = new Foo();
foo = new Bar();
Just as well like this:
object foo = new Foo();
foo = new Bar();
But the difference comes in when you want to use properties or methods. With dynamic, I can do this:
dynamic foo = new Foo();
foo.FooMethod(); // Note: You WILL get a runtime exception if foo doesn't have a FooMethod
But with an object, I'd need to do this:
object foo = new Foo();
((Foo)foo).FooMethod(); // Note: I HAVE to know the type at compile time here
Which I can only do if I already know I can cast the type in foo to a type of Foo at compile time, and if I knew that already, then I could just have use Foo as my type instead of object.

It means that a variable declared as dynamic will stay of type dynamic and cannot be changed to a variable of type int for example. This concept is bypassed though, because you can change the types of objects that the variable holds.
C# is considered as a strongly typed language because variables are statically typed. That means every variable is typed and the C#-compiler can check if the right types are used in the code. In weakly typed language like most script languages the type of variables is dynamic. They can hold any value.

Related

Is it possible to instantiate an object and pass it object initializer variables with Activator.CreateInstance? [duplicate]

I'm not sure of the terminology for this kind of code, but I want to know if it's possible to instantiate variables after the parentheses, but whilst using reflection.
I have a map which gets loaded from an XML file. This is a collection of (int X, int Y, string S) where the X,Y is the position of some terrain, and S is a string representing the type of the terrain. I have a dictionary to pass between the strings and the relevant types; for example one key-value pair might be "Tree", typeof(Tree).
When using reflection, although I know it's possible to instantiate with parameters, the only way I'm comfortable is just by using Activator.CreateInstance(Type t), i.e. with an empty constructor.
When I had the maps hard coded, I would originally instantiate like this (within some i,j for loop):
case: "Tree"
world.Add( new Tree(i,j) );
Whilst starting to think about reflection and my save file, I changed this to:
world.Add( new Tree() { X = i, Y = j }
However, I realised that this won't work with reflection, so I am having to do the following (Tree inherits from Terrain, and the dictionary just converts the XML save data string to a type):
Type type = dictionary[dataItem.typeAsString];
Terrain t = (Terrain)Activator.CreateInstance(type);
t.X = i;
t.Y = j;
world.Add(t);
I would prefer to do this using something like
Type type = dictionary[dataItem.typeAsString];
world.Add((Terrain)Activator.CreateInstance(type) { X = i, Y = j }
Is there any shortcut like this? I guess if not I could edit world.Add to take an X and Y and cast to Terrain in there to access those variables, but I am still curious as to a) what this {var1 = X, var2 = Y} programming is called, and b) whether something similar exists when using reflection.
This syntax is called Object Initializer syntax and is just syntactic sugar for setting the properties.
The code var result = new MyType { X = x } will be compiled to this:
MyType __tmp = new MyType();
__tmp.X = x;
MyType result = __tmp;
You will have to do that yourself using PropertyInfo.SetValue if you know the instantiated type only at runtime or use the normal property setters if the type is known at compile time.
The answer is no, because the object initialization syntax you mention (introduced with LINQ in 3.0) is an illusion of the compiler. As in, when you type this
var foo = new Foo { Bar = "baz" };
the compiler actually converts it into CLS-compliant IL which equates to
var foo = new Foo();
foo.Bar = "baz";
Phil Haack has a great blog post which not only covers the details of this rewriting done by the compiler, but also some side effects it can cause when dealing with types that implement IDisposable
As all of this is nothing but a feint by the compiler, there is no equivalent using reflection (i.e., Activator.CreateInstance(Type t)). Others will give you workarounds, but in the end there really is no direct equivalent.
Probably the closest generic hack you could manage would be to create a method that accepted an object, then used reflection in order to identify the properties of that object and their respective values in order to perform object initialization for you. It might be used something like this
var foo = Supercollider.Initialize<Foo>(new { Bar = "baz" });
and the code would be something like (this is off the top of my head)
public sealed class Supercollider
{
public static T Initialize<T>(object propertySource)
{
// you can provide overloads for types that don't have a default ctor
var result = Activator.CreateInstance(typeof(T));
foreach(var prop in ReflectionHelper.GetProperties(typeof(T)))
ReflectionHelper.SetPropertyValue(
result, // the target
prop, // the PropertyInfo
propertySource); // where we get the value
}
}
You'd have to get each property from the anonymous object, find a property in your target type with the same exact name and type, then get the value from that property in the anonymous object and set the value of your target's property to this value. Its not incredibly hard, but its absolutely prone to runtime exceptions and issues where the compiler chooses a different type for the anonymous type's property, requiring you be more specific (e.g., new { Bar = (string)null }), which screws with the elegance of the thing.
(T)Activator.CreateInstance(typeof(T), param1, param2, ...);
As described HERE.
public sealed class ReflectionUtils
{
public static T ObjectInitializer<T>(Action<T> initialize)
{
var result = Activator.CreateInstance<T>();
initialize(result);
return result;
}
}
public class MyModel
{
public string Name{get;set;}
}
And after that just make the call :
var myModel = ReflectionUtils.ObjectInitializer<MyModel>(m =>
{
m.Name = "Asdf"
});
The advantage is that in this way you will have type safety and use reflection as minimum required, because we all know that reflection is an expensive operation that should be avoided as much as possible.
You could create a constructor which takes those arguments, then use
Activator.CreateInstance(type, i, j)
But you won't be able to use the object initialization syntax. Which is just sugar candy for setting the properties.

Pass a var type variable to a function as reference?

Here is a sample piece of code where im trying to send a var type variable to another function as a reference parameter.
Type type = Type.GetType(te1.GetValue("class1"));
MethodInfo method = type.GetMethod("fnc1");
var obj1 = Activator.CreateInstance(type);
I cant use (class1)Activator.CreateInstance(type) since the variable class1 will be decided at runtime. That's why im using reflection here.
method.Invoke(obj1, new object[] { });
class2 cls2= new class2 ();
cls2.fnc2(ref obj1);//getting error 'cannot convert object to class type'
Im getting error as the fnc2 function receive parameter as a type of class1.
public string fnc2(ref class1 obj3)
{
}
How i can handle this? I need to get the parameter as a type of class1 using reflection. So i used the type var. I cant use dynamic since im using framework 3.5.
My requirement is create a object of class1>> execute a function of class1>> retain the object and pass that object to another function of class2 and process there.Also the name class1 and class2 will be decided dynamically and cannot be hard coded.
var is not a type. Rather it tells the compiler to "automatically determine the type" (and saves typing). Hover the mouse over the obj1 in the next line and Visual Studio will pop up a handy little box saying what the actual type is resolved to - as the error message indicates this is, well, Object.
(Some of the following may be outdated after updates to the question, but the same principles apply - the expression must be cast as appropriate type, which must be determined at compile-time, before it can be used as anything besides Object.)
A "solution" is just to cast the result of the Activator result (because we know this to be the case):
var obj1 = (class1)Activator.CreateInstance(type);
// same as: class1 obj1 = (class1)..
However, since we know this then we could avoid all that and use the following, which is boring:
var obj1 = new class1();
// same as: class1 obj1 = new class1();
So, now to the Y problem: this cannot be done for an arbitrary type and a cast is required. The types known by the compiler which can used as such in code must be known at compile-time; they cannot be directly resolved from run-time values.
If you're sure the type of obj1 is of the type your fnc2 expects then you could use reflection like so:
Type type = Type.GetType(te1.GetValue("class1"));
MethodInfo method = type.GetMethod("fnc1");
object obj1 = Activator.CreateInstance(type);
method.Invoke(obj1, new object[] {});
class2 cls2 = new class2();
cls2.GetType().GetMethod("fnc2").Invoke(cls2, new[] {obj1});
This retrieves the method called fnc2 (assuming there's only one with that name, no overloads) and invokes it with obj1. If there are overloads, you will need this GetMethod variant.
On a sidenote, using var in this case is really not that useful. For clarity, I think you should just use object.

How to use the type 'Type'

I know that I can use the type string as:
string someString = "This is my string";
I am not sure how to use the type Type
Type someType = someString.GetType();
How could I create a variable based on that type. I want to do something like
someType someOtherString = "here is another string";
//string
In other words, how could I create a variable based on some type?
There are a few ways to go about this, but the simplest would be to use the Activator class.
http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
Example:
Type t = someClassInstance.GetType();
object o = Activator.CreateInstance(t);
Variable types have to be known at declaration time. You can declare a variable of type object and then dynamically create an instance of a type which you only know about at execution time, but you can't dynamically declare a variable like that.
The closest you could get would be to create a generic type and instantiate that using a type argument specified with reflection. Then you really would have a variable of the right type - but you wouldn't be able to do anything particularly useful with it.
It's important to distinguish between the type of a variable and the type of the object a variable's value may refer to. For example:
object foo = Activator.CreateInstance(someType);
will end up with a variable of type object, but the value of foo will be a reference to an instance of whatever type someType refers to.
Try
var object = Activator.CreateInstance(myType);
Starting from C# 3 you can do:
var someOtherString = "here is another string";
This way you don't care what's the type, var is type "joker" and save you the need to know the type at declaration time.
Hope that's what you mean?
use Assembly.CreateInstance()
Type type = typeof(String);
Assembly asm = Assembly.GetExecutingAssembly();
object blah = asm.CreateInstance(type.FullName);

What is the difference between var foo = new Love(); AND object foo = new Love();?

As I am not familiar with implicit typing; can you please tell me the main differences between:
var foo = new Love();
AND
object foo = new Love();
In the first case the type of foo is Love. In the second case it is object.
var foo = new Love();
Here, the static type of variable foo is Love. It's equivalent to writing Love foo = new Love();.
object foo = new Love();
Here, the static type of variable foo is object. You cannot access any of Love's methods without using a cast first.
The dynamic type (or runtime type) of foo is Love in both cases, which is why GetType will return Love for both.
With var, the compile infers the type of the variable based on the expression on the right-hand side of the assignment operator.
In other words,
var foo = new Love();
is exactly equivalent to
Love foo = new Love();
So all the members of Love will be available via foo - whereas if foo were declared to be of type object, you'd only have access to GetHashCode(), ToString(), GetType() and Equals().
With var, you're still using static typing (as opposed to using dynamic in C# 4). You're just not explicitly stating the type of the variable - you're letting the compiler work it out for you. However, it does need to be a type that the compiler can work out. So for example, these are all invalid:
// All invalid
var a = null;
var b = delegate() { Console.WriteLine("Hello"); };
var c = x => Console.WriteLine("lambda: " + x);
var d = MethodName; // Attempted method group conversion
In these cases the compiler doesn't have enough information to work out which type you mean.
var foo = new Love();
here it equals to
Love foo = new Love();
sometimes we can use var to avoid long class name e.g. Dictionary<string,Dictionary<int,string>>. You can use all methods/properties of class Love.
object foo = new Love();
Now foo is considered to be an object, you can't see any method/property of class Love, but you can convert it back.

var vs Object in C# [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Difference between “var” and “object” in C#
I would like to know the difference between var and object.
When to use Var and when to use Object.
Pros and cons of using them.
var is just shorthand for "let the compiler pick the right variable type for me" (compile-time type-inference is the more exact term).
object, on the other hand, is a specific type; all other reference types derive from object, so you can assign anything to a variable of type object.
var is the answer when you find yourself asking, do I really have to type that long type name twice, in e.g.:
Dictionary<string, Func<List<Func<int, int, double>>, IEnumerable<Tuple<double, string>>>> myDict = new Dictionary<string, Func<List<Func<int, int, double>>, IEnumerable<Tuple<double, string>>>>();
Why no friend, you don't. Use var instead:
var myDict = new Dictionary<string, Func<List<Func<int, int, double>>, IEnumerable<Tuple<double, string>>>>();
Now myDict really is a Dictionary<string, Func<List<Func<int, int, double>>, IEnumerable<Tuple<double, string>>>>, so you can add things to it, enumerate it, etc.
If you declared it as object you couldn't do any operations with it that are provided by Dictionary, only the ones valid for all objects.
var is still strongly typed but with object you will have to cast everything.
var foo = "Hello, I am a string!";
// foo is a string, so this compiles
var fooCharArray = foo.ToCharArray();
object bar = foo;
// bar is not a string, so this does not compile
var barCharArray = bar.ToCharArray();
In the first example, the compiler knows that foo is a string and so we can call string methods on foo.
In the second example, we "upcast" the string foo to an object. Now the compiler does not know (because it shouldn't know!) that bar is actually a string, and we cannot call string methods on bar. The compiler will not allow implicit downcasting from an object (or any base type) to a derived type (such as System.String). Its part of compile time type safety rules.

Categories