Difference between dynamic and System.Object - c#

What is the difference between a variable declared as dynamic and a variable declared as System.Object? Running the following function would seem to indicate that both variables get cast to the correct type dynamically:
void ObjectTest()
{
System.Object MyTestVar = "test";
dynamic MyTestVar2 = "Testing 123";
Console.WriteLine("{0}", MyTestVar.GetType());
Console.WriteLine("{0}", MyTestVar2.GetType());
MyTestVar = 123;
MyTestVar2 = 321;
Console.WriteLine("{0}", MyTestVar.GetType());
Console.WriteLine("{0}", MyTestVar2.GetType());
}

The difference is that MyTestVar2.ToUpper() compiles and works, without any explicit casting.
object is a normal type.
dynamic is a basically a placeholder type that causes the compiler to emit dynamic late-bound calls.
GetType() is a normal function defined by the object class that operates on the instance that you call it on.
GetType() is completely unaffected by the declared type of a variable that refers to the object you call it on. (except for nullables)

You should probably start with this excellent MSDN article. The differences can be summed up quite succinctly:
At compile time, an element that is
typed as dynamic is assumed to support
any operation.
System.Object only has a handful of operations that it supports - ToString(), Equals(), etc.

The fundamental difference is compile-time(for object) vs runtime (for dynamic) resoulution of calls. Its also called early vs late binding. [ Note: add a reference to Microsoft.CSharp for the following code to compile.]
object o = "Hello world";// fine because a derived type can be assigned to a base type
dynamic d= "Hello world";// fine as well
Type otype=o.GetType();// compiles because it confirms that object has a GetType()
Type dtype=d.GetType();// also compiles but for another reason (i.e.no binding yet)
string upperd= d.ToUpper(); // compiles because no binding yet ( anything goes :)
string uppero= o.ToUpper(); // Fails to compile. Object has no ToUpper() method
If you comment out the last call , the application should run fine because the CLR , when it reaches the second last call d.ToUpper() at runtime, it will look for a method ToUpper() in the string type and will find it there (because in the second statement d was assigned a string). The last call did not compile because ToUpper() was being searched in the System.Object type at the compile time which of course will not be there.

The only difference in between object and dynamic.
In case of object you need to explicit type cast when you are going to retrieve value from object.
Kindly give a like if you find it suitable.

Related

Object type is same as type in inherited class [duplicate]

C# newbie question here. The following code (taken from the book "C# From Novice to Professional" by Christian Gross, Apress) gives an error:
worksheet.Add("C3", CellFactories.DoAdd(worksheet["A2"], worksheet["B1"]));
The reason is that the method DoAdd() does not accept the given arguments.
public static Func<object> DoAdd(Func<object> cell1, Func<object> cell2) {...}
VS claims that both args in the method call above are of type object whereas the method accepts only Func<object>. But the value of both worksheet elements is of type Func<object>:
worksheet.Add("A2", CellFactories.Static(10.0));
where this Static method just returns the given value:
public static Func<object> Static(object value) { return () => value; }
// return type= Func<object>
When I cast worksheet["A2"] as Func<object>, the code does work.
But there is something I don't understand. The type of the object instance is Func<object>. I have used the GetType() method to see proof of this, and compare the object types of the original elements to that of the cast object (which IS accepted):
Console.Writeline(worksheet["A2"].GetType());
// now cast to the correct type (why can't it do that implicitly, btw?)
Funk1 = worksheet["A2"] as Func<object>;
Console.Writeline(Funk1.GetType());
.. and they are ALL identical! (Type = System.Func'1[System.Object])
And even when I use the .Equals() method to compare both types, it returns true.
Yet, VS sees the first object instance as type object in the method call. Why? Why does the called method 'see' the argument as a different type than the GetType() returns?
(and if so, what good is the GetType() method?)
Thanks a lot for your advice/comments! (It's kinda hard to learn the language if the book examples give an error and you don't see the reason - hence, got the vague impression that something is wrong either with GetType() or VS.)
You need to understand the difference between dynamic typing and static typing. The indexer for your worksheet object most likely has a static type of object.
public object this[string cell]{get{...}set{...}}
Because all objects in C# inherit from type object, the object reference stored in a cell can be a reference to any object.
That is, because a delegate (such as Func<T>) is an object, it can be stored in an object reference:
Func<object> func = ()=>return "foo";
object o = func; // this compiles fine
And the compiler can figure this all out, because it understands implicitly that a derived class can be stored in a reference to a base class.
What the compiler cannot do automatically, is determine what the dynamic type, or run time type of an object is.
Func<object> func = ()=>return "foo";
object o = func; // this compiles fine
func = o; // <-- ERROR
The compiler doesn't know that the object stored in o is actually of type Func<object>. It's not supposed to keep track of this. This is information that must be checked at run time.
func = (Func<object>)o; // ok!
The above line of code compiles into something that behaves similarly to this:
if(o == null)
func = null;
else if(typeof(Func<object>).IsAssignableFrom(func.GetType()))
__copy_reference_address__(func, o); // made up function! demonstration only
else throw new InvalidCastException();
In this way, any cast (conversion from one type to another) can be checked at run time to make sure it's valid and safe.
Others have given accurate and detailed answers, but here I will try to explain in simple language.
When you write worksheet["A2"] you really are calling a member function of worksheet
worksheet has a member function named [] that accepts a string and returns an object
The signature of the member function [] looks like object this[string id]
So the function worksheet["A2"] returns something that is an object. It could be an int or a string or many other things. All the compiler knows is that it will be an object.
In the example, you have it returning a Func<object>. This is fine, because Func<object> is an object. However, you then pass the result of that function in as a parameter to another function.
The problem here is that the compiler only knows that worksheet["A2"] returns an object. That is as specific as the compiler can be.
So the compiler sees that worksheet["A2"] is an object, and you are trying to pass the object to a function that does not accept object as a parameter.
So here you have to tell the compiler "hey dummy, that's a Func<object>" by casting the returned object to the correct type.
worksheet.Add("C3", CellFactories.DoAdd(worksheet["A2"], worksheet["B1"]));
can be re-written as
worksheet.Add("C3", CellFactories.DoAdd((Func<object>)worksheet["A2"], (Func<object>)worksheet["B1"]));
Now the compiler knows that, even though the [] function returns an object, it can treat it like a Func<object>.
side note: You're probably doing too much on one line. That may be hard for people to read in the future.
Why does the called method 'see' the argument as a different type than the GetType() returns?
The compiler only knows that worksheet[] returns an object. The compiler can not call GetType() on it at compile time.
What good is the GetType() method?
There are quite a few uses and abuses of the GetType() method, but that is an entirely different discussion. ;)
In summary, the compiler does not assume anything about types. This is a good thing because you get a compile time error when you try to fit this square peg into a round hole. If the compiler did not complain, this error would surface at run-time, which means you would probably need a unit test to detect the problem.
You can get around this problem by telling the compiler "I know for a fact that this thing is a round peg, trust me." and then it will compile.
If you lie to the compiler, you will get a run-time error when that code is executed.
This is called "static typing". The opposing philosophy is called "dynamic typing" where type checks are done at run-time. Static vs dynamic is a lengthy debate and you should probably research it on your own if you're interested.
VS claims that both args in the method call above are of type object whereas the method accepts only Func. But the value of both worksheet elements is of type Func
Yes, but the declared type is object. The compiler can't know that the actual runtime type will be Func<object>, so an explicit cast is necessary.

Is casting string or reference type create another object in memory?

Today I am reading article and article shows the code snippet:-
string s1 = "Something";
string s2 = (string)s1.Clone();
if ((object).ReferenceEquals(s1, s2))
throw new Exception("But I need to know!");
Code snippet throws an error why? I can't understand what happened under a hood in CLR.
My question is a string or reference type casting create a new object or not?
From this MSDN Link, It specifically states The return value is not an independent copy of this instance; it is simply another view of the same data.
and that there is little reason to call it directly.
So, in short the Clone() method does not create a new copy. Type casting does not influence the instance of the data in memory, it merely provides another way of interpreting the same data.
The correct way to call a static method is to directly call that method on the type. class.Method(). By wrapping the type in parenthesis the compile considers this a cast of an instance.
Change this line ...
if ((object).ReferenceEquals(s1, s2))
... to this ...
if (object.ReferenceEquals(s1, s2))

casting and parsing between string, object and int

ddlSomeDropDownType.SelectedValue is a dropdown of .aspx page.
I have the following code:
int num = int.Parse(((object)this.ddlSomeDropDownType.SelectedValue).ToString());
Am I correct in thinking that the following happens:
Drop down value (string) gets down-casted to object
Object is a reference type so .ToString() doesn't do anything in this instance, gets omitted by the compiler
Object then gets parsed to int: ref type => value type
Or would the C# compiler pick up on that, and not cast when it doesn't have to?
drop down value (string) gets down-casted to object
Well, yes, but all that changes is how subsequent calls to the object are bound by the compiler. You're telling the compiler "treat this value as an object" It does not change the actual object in any way.
object is a reference type so .ToString() doesn't do anything in this instance, gets omitted by compiler
No - you call ToString which is a virtual method on object, so either object.ToString or a subsequent override will get called (in your case, string.ToString()`.
Plus, you've told the compiler to treat the value as an object. You expect the compiler to go back and say "well, I know you told me to treat it as an object, but I can tell from the code above that it's a string, so I'm going to ignore that and just keep it as a string". The compiler will not go to that effort. The JIT optimizer may do something similar if there is an iron-clad guarantee that it will work; otherwise it will do what you told it to do.
object than gets cast to int
No - it is parsed by the int class - very different than casting. It will read the characters of the string and attempt to return an equivalent integer value. The original object (the string) is untouched, and a new value (the int) is created. If you "change" the original value (which is impossible in this case because strings are immutable, but for sake of argument let's assume you can) then the parsed integer would not change. If you casted the object to int and then changed the string, they are both referencing the same value, so and changes would be reflected in both.
Since SelectedValue is a string, there's no need to cast to object and then call ToString(), so your code could be simplified to
int num = int.Parse(this.ddlDiscountType.SelectedValue);
No, not really.
First, you need to understand the difference between runtime type information and compile-time type information.
The compile-time type of ddlDiscountType.SelectedValue is string. When you cast it to object, it doesn't change the runtime type, just the compile-time type - in effect, you reduced the public interface of the reference.
ToString is a virtual method, so as long as you don't use new, what happens depends on the runtime type, and has no relation to the compile-time type, as long as the method is defined in the compile-time type. Since ToString is defined on Object, there's no problem.
The compiler cannot remove the call to ToString, because you've explicitly said "No, this reference is not really a string. It's just an object.", so you do have to make the virtual method call. The call will use the runtime type of the reference, so you're executing String.ToString(), which just returns this. But you did all your best to interfere with the compiler, and the compiler isn't going to second-guess you.
Finally, int.Parse will parse the string and output an integer. This involves going character by character through the string, of course. Reference and value types aren't important here - it's not a cast, it's a method call like any other. The method converts a string to a number, that's it. A cast would simply throw an InvalidCastException, because a string is not an integer (though if you make your own type, you can provide your own cast methods, which can do whatever you want them to do). The compiler can't tell you that you can't cast a string to an integer, because you just said the reference isn't really a string, but rather an object - and an object can be casted to a int, if it refers to a runtime type that is a boxed int.
There's no reason to do things in such a complicated manner. Just do:
var number = int.Parse(ddlDiscountType.SelectedValue);
Spend your effort in adding proper error handling instead of doing silly rituals :)
1: That's not correct. "Drop Down value (string) is Up-casted into object ".All classes in the .NET Framework are derived from object.(casting toward Base class is up-casting.)
2: a) Yes object is reference type.
b).ToString is object class method(can be override by derived classes). Actually what's going on here is that int.Parse takes string parameter. For that you first covert that into object and then .ToString method calls.
3:Yes 3rd point is correct

Dynamic binding vs type inference

In The C# Programming language Bill Wagner says:
Many people confuse dynamic binding with type inference. Type
inference is statically bound. The compiler determines the type at
compile time. For example:
var i = 5; //i is an int (Compiler performs type inference)
Console.WriteLine(i); //Static binding to Console.WriteLine(int)
The compiler infers that i is an integer. All binding on the variable
i uses static binding.
Now, given this information and my own made-up dynamic scenerio:
dynamic i = 5; //Compiler punts
Console.WriteLine(i);//This is now dynamically bound
We know type inference is statically bound. This implies that there is no way a dynamic variable can use type inference to determine a type. How does a dynamic type get resolved without using type inference?
Update
To try and clarify...at runtime we must somehow figure out what type i is right? Because I assign a literal 5 then the runtime can infer that i is an int. Isn't that type inference rather than dynamic binding?
What distinction is Bill making?
The distinction that Bill is making is that many people think that:
var x = Whatever();
x.Foo();
will work out at runtime what method Foo to call based on the type of object returned at runtime by Whatever. That's not true; that would be
dynamic x = Whatever();
x.Foo();
The var just means "work out the type at compile time and substitute it in", not "work it out at runtime".
So if I have
dynamic i = 5;
Console.WriteLine(i);
What happens?
The compiler generates code that is morally like this:
object i = (object)5;
DynamicCallSite callSite = new DynamicCallSite(typeof(Console), "WriteLine"));
callSite.Invoke(i);
It is a bit more complicated than that; the call site is cached, for one thing. But this gives you the flavour of it.
The invocation method asks i for its type via GetType and then starts up a special version of the C# compiler that can understand reflection objects. It does overload resolution on the members of Console named WriteLine, and determines which overload of Console.WriteLine would have been called had i been typed as int in the first place.
It then generates an expression tree representing that call, compiles the expression tree into a delegate, caches it in the call site, and invokes the delegate.
The second time you do this, the cached call site looks in its cache and sees that the last time that i was int, a particular delegate was invoked. So the second time it skips creating the call site and doing overload resolution, and just invokes the delegate.
For more information, see:
http://ericlippert.com/2012/10/22/a-method-group-of-one/
http://ericlippert.com/2012/11/05/dynamic-contagion-part-one/
http://ericlippert.com/2012/11/09/dynamic-contagion-part-two/
A historical perspective on the feature can be obtained from Chris and Sam's blogs:
http://blogs.msdn.com/b/cburrows/archive/tags/dynamic/
http://blogs.msdn.com/b/samng/archive/tags/dynamic/
They did a lot of the implementation; however some of these article reflect outdated design choices. We never did go with "The Phantom Method" algorithm, regrettably. (Not a great algorithm, but a great name!)

What is the difference between xxx.tostring() and (string)xxx?

whats the difference in the two string methods below?
string str1 = dr["RAGStatusCID"].ToString();
string str2 = (string)dr["Description"];
This will depend on what dr is. The first invokes the ToString method that each object could override on the indexer of the dr["RAGStatusCID"]. The second casts the dr["Description"] variable to a string.
If we use our telepathic skills and suppose that dr is a SqlDataReader then the two expression do pretty much the same thing except that the cast might throw an exception at runtime if the Description column is not a string.
You haven't mentioned the type of dr or what it's indexer operation returns, but ostensibly, these are two very different operations.
The first invokes the get indexer of dr and calls the ToString() method on the returned reference, allowing the object that reference refers to to provide a string representation of it's data. The generial intent of this is to allow the object itself to return a meaningful representation of itself as a string.
The second call attempts to cast the reference returned by the indexer to System.String. The object returned must either be an instance of System.String or must be a type that the compiler can invoke a custom conversion operator on. Here, the intent is to ensure that the object returned can be treated as an instance of System.String. You can read more about conversions (including user-defined ones) on MSDN.
First one calls the method that returns the string. Someone has to implement ToString method. Second one is just unboxing.
string str1 = dr["RAGStatusCID"].ToString();
This calls the .ToString() method on the object returned from the dr["RAGStatusCID"] call. It is guaranteed to return a string or null.
string str2 = (string)dr["Description"];
This attempts to cast the object returned by dr["Description"] to a string. If the object returned is not a string, then an exception is thrown.
in short, .toString() is a method, just like any other, (String) is a cast, a language construct used to treat one data type as another, compatible type.
Now for some detail:
.toString() is a method, just like any other method you may encounter. Its often thought to be a 'special' method in some way, but it isnt really, all it does is return a string. because its a member of the base Object type, it can be relied upon to be available in every object. For this reason it is generally used to provide a textual representation of the object of which it is member. By default, in c# this is the name of the type of the object. It is often desirable to override this method to provide a more meaningful name, but all it needs to do is return a string, this can be any string you like.
As noted before, theres nothing special about it, and you could just as easily have methods called ToInt(), ToDouble(), and ToChar() to provide the same functionality for there respective types.
Casting is a language construct, this means its built into the language and is implemented specifically for that language. It is used to enable compatible but different types to be used in different locations without the need for an explicit conversion.
xxx.ToString() calls a method on that object to convert it into a string object. (string)xxx assumes that the type of the object is already a string and simply performs a cast on the existing object. So in the first case a conversion happens, in the second it's just identifying the type explicitly.
To put it more succinctly, if in your example RagStatusCID is an integer and you attempted to call (string)dr["RagStatusCID"] you would get an exception because the type is not a string, it's an int. Calling .ToString() performs a conversion and the output is a string.
(string) is a casting operation. .ToString() is a method that is inherited from the Object class. Everything has a .ToString(), but not everything has a (string). Additionally certain objects will cast to a string different than the one .ToString() outputs.
I don't know if it is correct for C# but it probably is, so:
(String)myinstance calls implicitly the .toString() implementation of myinstance's class
if you have a class like this:
class User
{
private integer userId;
private integer userName;
... some code here...
public toString()
{
return "Username: " + this.userName + " (" + this.userId + ")";
}
}
with the method toString you are defining what (String)instance casting will do
User myuser = new User("Alex", 22);
String myuserdump = (String)myuser;
print(myuserdump);
will print "Username: Alex (22)"

Categories