Some misunderstanding in ChangeType method - c#

I'm a newer in c# so maybe my question will seem naive to some of you.
I'm using this method:
public static object ChangeType(object value, Type conversionType);
From metadata manual:
Returns:
An object whose type is conversionType and whose value is equivalent
to value.-or-A
null reference (Nothing in Visual Basic), if value is null and conversionType
is not a value type.
But in method signature the returned type always 'object'. So, what is the benefit in converting the value if returned type is object?

Convert.ChangeType creates a new object of the specified type, with a value equivalent to the object you passed.
For example, Convert.ChangeType("42", typeof(int)) will return a boxed int instance rather than a string.
The actual behavior is completely within the IConvertible implementation of the object you pass.

The reason is that you can cast to your particular type. This method comes from before generic types so the only way it could return one of any number of types is by returning the supertype of all of them, ie object. You can of course then cast that to your chosen type and guarantee you will be successful but the only other option would be an overload of every single type ever which would be a bit weighty. :)
The thing to note is that this isn't just the same as casting. It will return a whole new object which is the type you asked for rather than the type you gave it.

Also,
from the msdn documentation: http://msdn.microsoft.com/en-us/library/aa324833(v=vs.71).aspx
*
value An Object that implements the IConvertible interface.
*

In .net methods have a fixed signature (with generics you can go further, but that's not the case here) - so for this conversion method they chose the most common type: object.
Consider Person and Man. Man is defined as
class Man : Person
In order to create an address book, you would not create two methods:
Man GetByName(string name);
Woman GetByName(string name);
Instead you would create one method:
Person GetByName(string name);
This method would return a Person and even though the actual object returned is a Man, all you currently know about it is that it's a Person.
Back to the converter: you know the return type as you supplied it in the parameters, but a long time ago when the method was created they did not know what you were going to supply as parameter. You can safely cast the result to the type you already know:
MyType myObject = (MyType)ChangeType(value, typeof(MyType));

Related

"Blank" Generic Type Parameters - Use cases and explanation [duplicate]

Can somebody explain me the need in C# language for typeof(SomeGenericType<>), with no concrete parameters specified.
I put together the following example:
var t1 = typeof(Nullable<>);
var t2 = typeof(Nullable<int>);
var q = 1 as int?;
var b1 = t1.IsInstanceOfType(q); //false
var b2 = t2.IsInstanceOfType(q); //true
I first thought typeof(Nullable<>) is "more generic" than t2, which specifies generic parameter int, but b1 turns out to be false - so instance of int? is not instance of Nullable<>.
So how a variable should be defined for b1 to be true? what practical uses does it have?
So how a variable should be defined for b1 to be true?
It can't. (In fact, with Nullable<T> you'll run into interesting boxing problems anyway, but there we go...)
At execution time, values are always instances of closed types. Nullable<>, List<> are open generic types. It's never useful to call IsInstanceOfType on such a type. That doesn't mean it's useless though.
Typically open types are used in reflection. For example:
public IList CreateList(Type elementType)
{
Type closedType = typeof(List<>).MakeGenericType(elementType);
return (IList) Activator.CreateInstance(closedType);
}
There can be code high up which is generic, but calls into lower levels passing in Type values instead - the list could then go back up the stack and be cast to IEnumerable<T> for the appropriate value of T.
Likewise you may want to create a closed type with reflection to call a method on it, etc.
You can also use it to find out whether a particular type implements a generic interface for some type argument - for each interface implemented, you can find out if it's generic, get the generic type definition, and see whether that's equal to (say) IEnumerable<>.
That's an open generic type.
It's not an actual type; it is not possible to have an instance of that type.
Instead, you can use it to generate a concrete (closed) generic type, such as Nullable<int>.
You can also check whether a closed generic type is an instance of a particular open generic type by checking its GetGenericTypeDefinition() method.

What type is inside a generic container

public T getValueByName<T>(String name)
{
if( T is List )
Object containedType = T.WhatGoesHere()?
...
In the above code, I need to know if I can convert a List to whatever type of list is passed in, e.g., List<Control>.
Is there a way to interrogate the generic for the contained type? I could get List<Control>, List<String>, List<Form> etc..
I could split the API to return lists in a separate method where the contained type is passed in, thus requiring the caller to use one method for lists and one for simple types. Either way they have to know what's coming back, but if there's a smooth way to do what I'm asking about, I'd rather keep the API simple.
Note: this is a solution to the lack of covariance because even though there is an implicit conversion operator defined on the contained type, a cast of List to T fails. So, in order to follow the solution listOfB.Cast<A>(); from here, I need to know to what to cast (what is A).
Thanks!
You can start with typeof(T) to get an instance of System.Type that represents T.
Once you have that, you can check Type.IsGenericType to see if it really is a generic and then call Type.GetGenericArguments() to see what generic arguments were used.
For example, if T was List<int> IsGenericType would be true and GetGenericArguments() would return an array containing one element: System.Int32
For example, here is a snippet of code I wrote to see if a given type (variable type) is some implementation if IEnumerable<T> where T is not known. It first has to see if it is a generic, then work out whether it has only one argument, determine said argument and see if it implements the interface, given that argument:
if (type.IsGenericType)
{
Type[] genericArguments = type.GetGenericArguments();
if (genericArguments.Length == 1)
{
Type proposedEnumerable = typeof(IEnumerable<>).MakeGenericType(genericArguments);
if (proposedEnumerable.IsAssignableFrom(type))
{
For reference, see:
http://msdn.microsoft.com/en-us/library/system.type.isgenerictype(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/system.type.getgenericarguments(v=vs.110).aspx

(open generic type) typeof generic type with no parameters specified

Can somebody explain me the need in C# language for typeof(SomeGenericType<>), with no concrete parameters specified.
I put together the following example:
var t1 = typeof(Nullable<>);
var t2 = typeof(Nullable<int>);
var q = 1 as int?;
var b1 = t1.IsInstanceOfType(q); //false
var b2 = t2.IsInstanceOfType(q); //true
I first thought typeof(Nullable<>) is "more generic" than t2, which specifies generic parameter int, but b1 turns out to be false - so instance of int? is not instance of Nullable<>.
So how a variable should be defined for b1 to be true? what practical uses does it have?
So how a variable should be defined for b1 to be true?
It can't. (In fact, with Nullable<T> you'll run into interesting boxing problems anyway, but there we go...)
At execution time, values are always instances of closed types. Nullable<>, List<> are open generic types. It's never useful to call IsInstanceOfType on such a type. That doesn't mean it's useless though.
Typically open types are used in reflection. For example:
public IList CreateList(Type elementType)
{
Type closedType = typeof(List<>).MakeGenericType(elementType);
return (IList) Activator.CreateInstance(closedType);
}
There can be code high up which is generic, but calls into lower levels passing in Type values instead - the list could then go back up the stack and be cast to IEnumerable<T> for the appropriate value of T.
Likewise you may want to create a closed type with reflection to call a method on it, etc.
You can also use it to find out whether a particular type implements a generic interface for some type argument - for each interface implemented, you can find out if it's generic, get the generic type definition, and see whether that's equal to (say) IEnumerable<>.
That's an open generic type.
It's not an actual type; it is not possible to have an instance of that type.
Instead, you can use it to generate a concrete (closed) generic type, such as Nullable<int>.
You can also check whether a closed generic type is an instance of a particular open generic type by checking its GetGenericTypeDefinition() method.

What is the difference of getting Type by using GetType() and typeof()? [duplicate]

This question already has answers here:
Type Checking: typeof, GetType, or is?
(15 answers)
Closed 1 year ago.
Which one is the preferred way to get the type?
You can only use typeof() when you know that type at compile time, and you're trying to obtain the corresponding Type object. (Although the type could be a generic type parameter, e.g. typeof(T) within a class with a type parameter T.) There don't need to be any instances of that type available to use typeof. The operand for typeof is always the name of a type or type parameter. It can't be a variable or anything like that.
Now compare that with object.GetType(). That will get the actual type of the object it's called on. This means:
You don't need to know the type at compile time (and usually you don't)
You do need there to be an instance of the type (as otherwise you have nothing to call GetType on)
The actual type doesn't need to be accessible to your code - for example, it could be an internal type in a different assembly
One odd point: GetType will give unexpected answers on nullable value types due to the way that boxing works. A call to GetType will always involve boxing any value type, including a nullable value type, and the boxed value of a nullable value type is either a null reference or a reference to an instance of a non-nullable value type.
GetType() works at runtime, typeof() is a compile-time operator.
So,
// untested, schematic
void ShowType(Object x)
{
Write(x.GetType().Name); // depends on actual type
// typeof(x) won't actually compile
Write(typeof(x).Name); // always System.Object
}
ShowType("test");
Will print System.String and System.Object.
See this question for a better example.
GetType is a virtual method on Object - this means given an instance of a class, you can retrieve the corresponding Type object.
typeof is a C# operator - this is used to perform a compile time lookup i.e. Given a Symbol representing a Class name, retrieve the Type object for it.
if (typeof(String) == "test".GetType())
It's not exactly the same, and the problem appears when you use
inheritance.
I.e.:
WebPage1 inherits from Page, and this one inherits also from Object, so if you test for (new WebPage1()).GetType() == typeof(object) it'll return false because the types are diferent, but when you test using the is operator it's true.
((new WebPage1()) is object) is true because (new WebPage1()) is an object of type WebPage1, and also a Page and an object.
The types might be different, but is checks if you can cast safely to
this type.

(C#) why does Visual Studio say it's an object while GetType says it's a Func<object>?

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.

Categories

Resources