If i have a type and an object eg.:
- Type someType (coming from somewhere, could be any class eg. MyClass.GetType())
- Object someObject (eg. List<MyClass>())
and want to cast the object back to List<MyClass>. How should i do this?
You can't do this. Generics ensure compile-time safety. You cannot have compile time safety because you know the actual type only at runtime.
You have a runtime type and you want to perform a compile time cast. This is not possible. It is also not clear why you would want to do this in the first place. If you are interested in cases that require reflection, perhaps you should investigate that topic further.
There is no way to have compile-time typing a variable when you only receive the Type information at runtime.
This is different from generics since in generics you get the type information at compile time:
void MyFunc<T>(T thing)
{
// T is passed in at compile time
}
In your case you are getting the type at runtime. So while you can't cast the member to the type the way you normally would you can reflect on the instance and call its members:
void MyFunc(object thing, Type type)
{
var res = t.GetMethod("Add").Invoke(a, new []{"someArg"});
}
Casting means explicitly specifying the type you want to convert to. Since you don't know what your type is, you can't cast to it.
That doesn't mean you can't access the list. If you know the object you have is a list of something, you can cast it to the non-generic IList interface, which provides most of the methods and properties you need:
object obj = GetMyList();
IList list = (IList)obj;
object fifthItem = list[4];
list.RemoveAt(list.Count - 1);
If you describe the problem you're trying to solve rather than the solution you are trying to achieve, then more fitting solutions might be posted.
If you are trying to cast a runtime type at compile time, it is impossible as may said before me.
However, you could cheat a little (but don't use this technique excessively, it leads down a dark road...)
public void DoSomething<T>(List<T> object) where T : ....
{
//do what you want here
}
public void CallIt(Type t, object o) //o is List<Foo>
{
this.GetType().GetMethod("DoSomething").MakeGenericMethod(t).Invoke(o);
}
However I don't see any real benefit to this, as if you don't write any type constraint you gain nothing with using generics instead of objects and IList interface, and if you write any baseclass or interface there, you could just cast your object to that. (For example if you know that T implements IFoo, you could cast o to IList<IFoo> and have every benefit of List<Foo>...
Related
When I was learning C# generics, some articles mentioned using generics is type-safe during execution by preventing the usage of data whose type is different from the one used in the declaration.
Link
I dont get why this should be an issue, if type is wrong shouldn't it crashed when build?
I'm curious about when and how this kind of problem could happen.
I'm curious about when and how this kind of problem could happen.
Basically, when using types that don't support generics but could. The classic example is probably ArrayList - the pre-generics equivalent of List<T>. ArrayList.Add just accepts object, so you can add anything into it - but typically code assumes just a specific type. So for example:
var people = new ArrayList();
people.Add(new Person("Jon"));
// ... later in the code
foreach (string name in people)
{
Console.WriteLine(name);
}
That crashes with a ClassCastException, because the list contains a Person reference, which is then implicitly cast to a string reference. That wouldn't happen with generics, where you'd have either a List<Person> or a List<string>, and spot errors at compile-time.
Generics are indeed type safe in compile time. I'd say that article in the sentence:
Client code that uses generics is type-safe during execution by
preventing the usage of data whose type is different from the one used
in the declaration
is referring to the implicit benefit of eliminating runtime invalid cast exceptions.
Generics provide type safety during compile-time, meaning you can't compile your code if the generic constraint is violated. And that is almost always preferable over a runtime exception.
void DoSomething<T>(T foo) where T : FooBase { }
If I try now to write code like this:
var myBar = new Bar(); // Does not inherit from FooBase
DoSomething(myBar);
Then I get this:
error CS0311: The type 'Bar' cannot be used as type parameter 'T' in the generic type or method 'DoSomething(T)'. There is no implicit reference conversion from 'Bar' to 'FooBase'.
And this happens during compile time. Perfect.
You might have also seen generics without any constraint:
void DomSomething<T>(T foo);
This will go a bit away from your original question, but one could ask what is the benefit over let's say: DoSomething(object obj). And here we have a difference between value types and reference types - namely boxing and unboxing happens when using the version with object.
So generics can also have some performance benefits, next to the type safety and reusability aspect.
One of the major benefits of generics in not just type-safety as is, but allowing writing generalized code while still maintaining type-safety and without degrading performance for value-types. For example we can generalize over collection of interface:
public interface IHaveId { int Id {get;}}
public T GetOrAddById<T>(IList<T> col, int id, T val) where T : class, IHaveId
{
var item = col.FirstOrDefault(x => x.Id == id);
if (item == null)
{
item = val;
col.Add(item);
}
return item;
}
Now you can't pass anything that does not implement the concrete interface.
Before the generics the only way of having generalized collection would be something like ArrayList (which can be compared to List<object>), so user could put anything in it without any type-safety.
I have some method with the following definition;
public void SomeMethod<T>() where T : BaseClass, new()
{
InheritedClass instance = (InheritedClass)instanceOfT; //won't compile
}
Why is that cast not allowed? How can you get around this? I have about 200 lines of code which is all suited for generics except I need a one LINQ query for each of the inheriting classes (there are 3). I was trying to do a typeof check, then follow that with a cast, then execute the appropriate query but the compiler won't let me do the cast... Given I just checked to ensure that T is in fact an instance of type InheritedClass there is no way it would fail, why won't the compiler let me do it?
You need to cast the variable to object and then back down to do this. As it is the compiler believes that there is no possible way that the cast could succeed, but it doesn't ever apply that check to variables of type object.
InheritedClass instance = (InheritedClass)(object)instanceOfT;
Because the actual instanceOfT's type (let's call it InheritedClassB) may not be related to InheritedClass.
Given I just checked to ensure that T is in fact an instance of type InheritedClass
Actually, you're only checking that T extends BaseClass.
Edit: This looks like a code smell.. Can't you let the concrete class handle this method? So each concrete class would have its own implementation, and know how to perform SomeMethod.
I've combed through existing questions/answers on this matter, but none of them spelled out exactly what I was looking for in a way I understood. Here is my snippet:
Type t = **?**
_SecondRole.ProvisionRelationship<t>(_FirstRole);
I believe I'm suppose to use reflection here, though I don't fully understand how. How do I define "t" so this works?
Thank you for any assistance.
If the _FirstRole is an instance of the unknown t, for example from:
object _FirstRole = Activator.CreateInstance(t);
then you can exploit dynamic here:
dynamic _FirstRole = Activator.CreateInstance(t); // or whatever
_SecondRole.ProvisionRelationship(_FirstRole);
The second line is now a dynamic statement, evaluated in part at runtime (but with some clever cache usage) - which means it can perform generic type inference from the actual type of the object dereferenced from _FirstRole.
If that is not the case, then the only way to invoke that is via GetMethod and MakeGenericMethod - which is ungainly and not hugely efficient. In that scenario I would strongly suggest refactoring _SecondRole.ProvisionRelationship to accept a Type parameter rather than just being generic; you can of course still provide a generic version to avoid impacting existing code:
void ProvisionRelationship(Type type, SomeType role) {...}
void ProvisionRelationship<T>(SomeType role) {
ProvisionRelationship(typeof(T), role);
}
and invoke as:
_SecondRole.ProvisionRelationship(t, _FirstRole);
I have this:
public IClub GetTeam()
{
return new Arsenal();
}
//compiles since Arsenal is an IClub
public T GetTeam<T>() where T : IClub, new()
{
return new Arsenal();
}
//wouldn't compile saying "cannot convert Arsenal to T"
But these things work:
public T GetTeam<T>() where T : IClub, new()
{
T t = new T();
t.Sponsor = "Nike"; //since it knows T is IClub,
return new T(); //but why the injustice to return type alone?
}
Why wouldn't the second code block compile even though return type is anyway IClub? Isn't that injustice?
I know I am not fully utilizing the potential of type constraints in above code but what is an alternative to get the code running?
It's because at compile time the compiler does not know whether Arsenal will be convertible to T. T could be another type implementing IClub after all. like in GetTeam<WhateverTeam>(). WhateverTeam implements IClub, but you cannot convert Arsenal to that.
You'd have to cast the result if you want your code to compile (as in Marc-André's answer), but you should rather rethink your design (also calling GetTeam<WhateverTeam>() would result in an exception). Making that method generic doesn't make sense if you already know which type you will return.
T is an unknown type at compile time and the compiler have no way to know if they can be cast from one type to another, so you much explicitly call for a cast toward that type.
return (T)(object)(new Arsenal());
This way, the compiler know for sure that Arsenal can be cast as an object, and that object can be cast as T.
You will get a runtime assert if the cast is invalid, but it will compile and work fine if it cast correctly.
Why T is unknown if you constraint it to IClub? Because any type could implement this interface. You try to return Arsenal, but another class, let's say "Car : IClub" also implement IClub. In this case, T can be Car, but the compiler has no way to prove that Arsenal could be cast into Car... Or any other class for that matter as it only knows which interface it implement, not it's real identity.
I need to create a heterogeneous List of objects (custom classes). My first thought was to create a List<ISomeMarkerInterface> but I quickly learned that this is not what I want. My next thought was List<dynamic> and this didn't seem to be a bad idea. However, I was doing some research and came across this article about boxing and unboxing and in the example, they're doing basically what I want using List<Object>.
Aside from the fact that dynamic will be evaluated at runtime and Object at compile-time, what is the difference between List<dynamic> and List<Object>? Aren't they essentially the same thing?
There are 3 "general" types (although not all are real types) in C#: object, var and dynamic.
Object
An actual type, like any other type, with one special rule: if a type doesn't inherit, it inherits from object. From this, it follows that all types inherit from object, directly or indirectly.
Emphasis: object is a type. An object can be of type object, and the type has its methods, like ToString(). Since everything inherits from object, everything can be upcast into object. When you assign an object to an object reference, you are doing upcasting just like when you assign an Elephant type object to an Animal reference where Elephant inherits from Animal.
SomeType x = new SomeType();
object obj = x;
obj.DoSomething();
obj is treated as being of type object at compile time, and will be of type object at runtime (which is logical, since it is an actual type - obj is declared as object so can only be of that type)
obj.DoSomething() will cause a compile-time error, as object does not have this method, regardless of whether SomeType has it.
Var
This is not an actual type, it is merely shorthand for "compiler, figure out the type for me based on the right side of the assignment".
SomeType x = new SomeType();
var obj = x;
obj.DoSomething();
obj is treated as being of type SomeType at compile time, and will be of type SomeType at runtime, just as if you had written "SomeType" instead of "var".
if SomeType has a method DoSomething(), this code will work
if SomeType doesn't have the method, the code will cause a compile-time error
Dynamic
This is a type that tells the compiler to disable compile-time type checking on the variable. An object is treated as having the type dynamic at compile-time and run-time.
SomeType x = new SomeType();
dynamic obj = x;
obj.DoSomething();
obj is of type dynamic at compile and run time
if SomeType has a method DoSomething(), this code will work
if SomeType doesn't have the method, the code will compile, but throw an exception at run-time
note that dynamic can cause exceptions very easily if used carelessly:
public void f(dynamic x)
{
x.DoSomething();
}
This will throw an exception if x is of a type that doesn't have the DoSomething method, but it will still be possible to call it and pass any object as the parameter without a compile-time error, causing an error that only shows itself at run-time, and possibly only in specific circumstances - a potential bug. So if you use dynamic in any kind of public interface of a class, you should always manually type-check at runtime using reflection, carefully deal with exceptions, or not do it in the first place.
Note: the object being referred to never changes its type, of course. While obj may be object, the x that it refers to is still SomeType.
The difference is that if you use object and you try to access some member of your object it will be a compile time error (because object doesn't have this member). In order to work you need to know what the type is and cast it.
With dynamic you can access any member - no compile time error. If the member doesn't exist at runtime it would be a runtime error. This is the way to go if you know that your heretogeneous objects all have the same member for example.
However if this is the case there is another more clear solution: You can define an interface, with this member and then make all your heretogeneous objects implement it and your list can be List<IYourInterface>.
Keep in mind that dynamic's performance might be slightly worse, because of the, well, dynamic type resolution.