There is a tool I'm modifying as I want to be able to use a generic type.
It has properties "AsDouble", "AsBool", etc.
I want to force a typecast and I don't care if it throws in runtime. I just want it to compile.
So... this does not compile...
public T As<T>()
{
Type type = typeof(T);
if (type == typeof(Double))
{
return (T)(AsDouble);
}
// more conditionals
}
Yet this does...
public T As<T>()
{
Type type = typeof(T);
if (type == typeof(Double))
{
return (T)(AsDouble as object);
}
// more conditionals
}
Why is it acting like this? How do I make it stop complaining and just do what I ask it too? Or is there a much better way of doing this than what I have in mind?
// Not duplicate of the one suggested. (Type1)Type2 does not work... I am wondering why converting from T1 to T2 to T3 works but not T1 to T3. (T1 being double, T2 being object, T3 being generic type.) Please read my question before flagging it as a duplicate.
If T does not have any type constraints the compiler will not know what type of casting to do as the relation between T and double is not known. The only way I know to achieve what you want is to cast through object, which might generate a box/unbox operation (it might get optimized but I am not sure).
In the case of generic methods with clear specializations by type I have employed the following pattern:
class Owner
{
class AsHelper<T>
{
public static Func<Owner, T> As;
}
static Owner()
{
AsHelper<double>.As = _ => _.AsDouble;
// Other implementations
}
public T As<T>() where T: struct
{
if(AsHelper<T>.As != null)
{
return AsHelper<T>.As(this);
}
else
{
// Default implementation or exception
return default(T);
}
}
}
This keeps the specializations in their own methods. From my performance testing it does about the same as the if base approach. Since statics are per generic class instantiation in .NET not per generic class definition the As field of AsHelper<T> will have a different value for each T
Related
I have a type that uses generics. Let's call it FlowerDescriptor<T> some flowers are described using numbers, others using strings etc.
so FlowerDescriptor<int>; FlowerDescriptor<string>; etc
I want a mechanism (probably extension methods) for doing 2 things
seeing if something is a FlowerDescriptor and
seeing what the descriptor is.
I.e.
FlowerDescriptor<string>.GetType().IsFlowerDescriptor == true
string.GetType().IsFlowerDescriptor == false.
equally I might derive from FlowerDescriptor<int> i.e. class NumberedFlower: FlowerDescriptor<int>
new NumberedFlower.GetType().IsFlowerDesriptor == true;
as above but returns the type
FlowerDescriptor<string>.GetType().GetFlowerDescriptor() == typeof(string)
FlowerDescriptor<int>.GetType().GetFlowerDescriptor() == typeof(int)
new NumberedFlower.GetType().GetFlowerDescriptor() == typeof(int)
I have played about with variations of IsAssignableFrom and it feels like that ought to work with typeof(FlowerDescriptor<>).IsAssignableFrom(typeof(FlowerDescriptor<string>))
but it doesn't work. If it add the generic type however it does.
I am currently exploring GetInterfaces to know available interfaces. It'd be great to actually understand what I am doing wrong too..
Unless you want to add interfaces into the mix, the only choice you have is to
Detect that the type is actually a FlowerDescriptor<T>
or detect that the type inherits from something that is a FlowerDescriptor<T>
Unfortunately I don't think you can use IsAssignableFrom when it comes to open generics which means we're left with walking the inheritance chain up to the base classes.
Here is an example piece of code that would do the right thing:
public static bool IsFlowerDescriptor(this Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(FlowerDescriptor<>))
return true;
if (type.BaseType != null)
return type.BaseType.IsFlowerDescriptor();
return false;
}
Here's a .NET Fiddle you can experiment with.
I would not expect the string or int class to know if its a descriptor, it makes a lot more sense to get that information from the FlowerDescriptor.
That being said if you want to use reflection you could get the generic type definition from the FlowerDescriptor instance
FlowerDescriptor<int> f = new FlowerDescriptor<int>();
Type t = f.GetType();
Type[] typeArguments = t.GetGenericArguments();
//check if type you care about is in typeArguments
Here is how you would get those two values:
bool isFlowerDescriptor = x is FlowerDescriptor<object>;
Type descriptorType = x.GetType().GetGenericArguments()[0];
You could wrap these in extension methods if you like. And add null-checks etc.
You might consider having a non-generic base class. Then your structure could look like:
public abstract class FlowerDescriptor { }
public class FlowerDescriptor<T> : FlowerDescriptor { }
public class NumberedFlower : FlowerDescriptor<int> { }
Your 2 extensions would be:
public static class Extensions
{
public static bool IsFlowerDescriptor(this object o)
{
return o is FlowerDescriptor;
}
public static Type GetFlowerDescriptor<T>(this FlowerDescriptor<T> o)
{
return typeof (T);
}
}
and you'd use it like:
public static void Main()
{
Console.WriteLine(new NumberedFlower().IsFlowerDescriptor()); //true
Console.WriteLine(new NumberedFlower().GetFlowerDescriptor()); //System.Int32
}
Generics have an adverse effect when it comes to reflecting over and comparing types, because a FlowerDescriptor<int> is a different type from FlowerDescriptor<string>. This is something I have not found a good rhythm for.
I need to test if a value is an instance of a generic base class, without knowing the generic type parameter. Using the MSDN example as the base of my example, this is what I'd like to accomplish:
using System;
public class Class1<T> { }
public class DerivedC1 : Class1<int> { }
class IsSubclassTest
{
public static void Main()
{
Console.WriteLine(
"DerivedC1 subclass of Class1: {0}",
typeof(DerivedC1).IsSubclassOf(typeof(Class1<>)) // <- Here.
);
}
}
While this is syntactically correct, it always yields false. If I remove the generic type parameter, it works as expected (returns true).
How can I test if a class type is a subclass of a generic base class, without knowing its generic type parameter as such?
The problem is that DrevidedC1 is not a sublcass of Class1<T>, it's a subclass of Class1<int>. Make sure you understand this subtle diference; Class1<T> is a open type (T can be anything, it hasn't been set) while DerivedC1 extends a closed type Class1<int> (it's not open in T anymore, T is set to int and only int). So when you do the following:
typeof(DerivedC1).IsSubclassOf(typeof(Class1<>))
The answer is evidently false.
What you need to do is check if the generic type definition of DerivedC1's base type (think of it as the corresponding open generic type of Class1<int>) equals Class1<T> which it clearly does.
The correct code is therefore:
typeof(DerivedC1).BaseType.GetGenericTypeDefinition() == typeof(Class1<>));
Or better yet, as MatÃas Fidemraizer states in his answer:
typeof(DerivedC1).BaseType.GetGenericTypeDefinition().IsAssignableFrom(typeof(Class1<>)));
There's special methods on Type for this sort of thing. As far as I can see, you'll need to walk up your base-types and check each in turn until you either (a) hit a match or (b) get to the top of the inheritance hierarchy (i.e. System.Object).
As such, the following (recursive) extension method:
public static class TypeExtensions
{
public static bool IsDerivedFromGenericParent(this Type type, Type parentType)
{
if(!parentType.IsGenericType)
{
throw new ArgumentException("type must be generic", "parentType");
}
if(type == null || type == typeof(object))
{
return false;
}
if(type.IsGenericType && type.GetGenericTypeDefinition() == parentType)
{
return true;
}
return type.BaseType.IsDerivedFromGenericParent(parentType)
|| type.GetInterfaces().Any(t=>t.IsDerivedFromGenericParent(parentType));
}
}
will allow you to do the following
typeof(DerivedC1).IsDerivedFromGenericParent(typeof(Class1<>))
...and will also work if you test something derived from DerivedC1.
Changing typeof(DerivedC1).IsSubclassOf(typeof(Class1<>)) to typeof(Class1<>).IsAssignableFrom(typeof(DerivedC1).BaseType.GetGenericTypeDefinition()) should be enough in your case.
Type.IsAssignableFrom is more powerful than using Type.IsSubClassOf because it just checks if some type is assignable to other type. This includes, the same type, interface types and other cases.
public class BaseGenericType<T>
{
}
public class SubGenericType<T>: BaseGenericType<List<T>>
{
}
I have two generic types above, which one inherits from another but is still generic.
The strange thing I can't figure out is that typeof(SubGenericType<>).IsSubclassOf(typeof(BaseGenericType<>)) returns false. And typeof(SubGenericType<>).IsSubclassOf(typeof(BaseGenericType<List<>>)) still returns false. I've tried GetGenericTypeDefinition() and MakeGenericType() and GetGenericArguments() to check the inheritance, still not working. But typeof(SubGenericType<int>).IsSubclassOf(typeof(BaseGenericType<List<int>>)) returns true.
What I want is to get all classes by reflection then grab the specific class which inherits from a generic type passed in.
e.g.
(1)List<int> -->
(2)get generic type definition ==> List<T> -->
(3)make generic ==> BaseGenericType<List<T>> -->
(4)find subclass ==> SubGenericType<T>
(5)make generic ==> SubGenericType<int>
In step (4) I find nothing although I actually have that SubGenericType<T>. Why is that?
Once I wrote this method to check generic type inheritance:
static bool IsSubclassOfOpenGeneric(Type generic, Type toCheck)
{
while (toCheck != null && toCheck != typeof(object))
{
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur)
{
return true;
}
toCheck = toCheck.BaseType;
}
return false;
}
This returns true:
IsSubclassOfOpenGeneric(typeof(BaseGenericType<>), typeof(SubGenericType<int>))
It doesn't check interfaces though.
By the way, usually if you have relations like this, and you write all the classes yourself, consider using interfaces. It is much easier to handle. You can for instance have a IGenericType interface without generic argument. Sometome you just do not care about the generic type and just want to access members which do not depend on the generic type. Sometimes you want to simply check if it is one of those. And you can use type variance.
Finally, I figured it out.
This is the very solution. To explain in details, I have to introduce some non-abstract coding:
It's about a value converter. My purpose is simple, to let users add their own value converters. In the conversion step, I will check built-in types' converters first(as IConvertible), if not found, I'll first search the current executing assembly for all custom converter classes that inherit a specific abstract class provided by me. And an interface is implemented by that abstract class to make constraint for later reflection. Then I filter those reflected classes for the one that matches.
Here is the base class and interface(all nested):
private interface ICustomConverter
{
Type SourceType { get; }
object CallConvert(string input);
}
public abstract class CustomConverter<T> : ICustomConverter
{
public abstract T Convert(string input);
public Type SourceType
{
get { return typeof (T); }
}
object ICustomConverter.CallConvert(string input)
{
return Convert(input);
}
}
I've made the interface private in the parent class and implemented explicitly. So that the method CallConvert() won't be called outside.
The generic parameter T is the Type to convert the string value to.
e.g.
public class Int32Converter:CustomConverter<int>
{
}
This is easy to handle since the conversion target type isn't generic. all I need to do is to get all types that implement ICustomConverter, and make a generic type from CustomConverter<T> with the given int, thus CustomConverter<int>. Then I filter those classes for the one that derives from CustomConverter<int>, and here I found Int32Converter.
Later I came across this situation:
public class ListConverter<T>:CustomConverter<List<T>>
{
}
and
public class DictConverter<T,U>:CustomConverter<Dictionary<T,U>>
{
}
I used the same process to deal with them. But after I made a generic type CustomConverter<List<T>>, I found that ListConverter<T> does not derive from CustomConverter<List<T>> and CustomConverter<List<T>> is not assignable from
ListConverter<T>(which I checked with IsAssignableFrom() and IsSubclassOf()).
I guess the reason is that generic type stands for more than one type before the generic parameters are assigned.
This sounds weird but it is true. The compiler doesn't know that the T in CustomConverter<List<T>> and ListConverter<T> stand for the same TYPE
In fact, I can write it like CustomConverter<List<T>> and ListConverter<U>, and then you tell me the inheritance relationship between them.
And base type checking won't work here since ListConverter<T> and DictConverter<T,U> share the same root class. This means if I look for ListConverter<T>, I'll get DictConverter<T,U> too with the base class checking method(hierarchy loop checking). So I still have to make generic type, then check generic arguments and do type comparing.
The point is that I need to look for the specific class whose generic parameters are used as the generic arguments in its parent class's generic parameter. Sort of twisted but now it is clear.
Here is the final Convertion solution:
public static object ToObject(Type type, string value)
{
if (type == null)
throw new ArgumentNullException("type");
if (!typeof (IConvertible).IsAssignableFrom(type))
{
if (type.IsGenericType)
{
Type converterType = typeof (CustomConverter<>).MakeGenericType(type);
Type genericConverter =
typeof (ICustomConverter).Assembly.Types(Flags.Public)
.SingleOrDefault(
t =>
typeof (ICustomConverter).IsAssignableFrom(t) && t.IsGenericType &&
t.GetGenericArguments().Length == type.GetGenericArguments().Length && !t.IsAbstract &&
t.MakeGenericType(type.GetGenericArguments()).IsSubclassOf(converterType));
if (genericConverter != null)
{
Type customConverter = genericConverter.MakeGenericType(type.GetGenericArguments());
object instance = customConverter.CreateInstance();
if (instance is ICustomConverter)
return ((ICustomConverter) instance).CallConvert(value);
}
}
else
{
Type converterType = typeof (CustomConverter<>).MakeGenericType(type);
Type customConverter =
typeof (ICustomConverter).Assembly.Types(Flags.Public)
.SingleOrDefault(t => t.IsSubclassOf(converterType));
if (customConverter != null)
{
object instance = customConverter.CreateInstance();
if (instance is ICustomConverter)
return ((ICustomConverter) instance).CallConvert(value);
}
}
throw new ArgumentException("type is not IConvertible and no custom converters found", type.Name());
}
TypeConverter converter = TypeDescriptor.GetConverter(type);
return converter.ConvertFromString(value);
}
I also checked GetGenericArguments().Length in case List<T> messes with Dictionary<TKey,TValue>.
Note: some custom extension methods are used.
This question already has answers here:
Cast from Generics<T> to Specific SubClass
(9 answers)
Closed 7 years ago.
I have a simple interface and two classes implement it:
public interface IMovable { }
public class Human : IMovable { }
public class Animal : IMovable { }
The following generic method results in a compile-time error: Cannot convert type 'Human' to 'T'
public static T DoSomething<T>(string typeCode) where T : class, IMovable
{
if (typeCode == "HUM")
{
return (T)new Human(); // Explicit cast
}
else if (typeCode == "ANI")
{
return (T)new Animal(); // Explicit cast
}
else
{
return null;
}
}
But when the as keyword is used, all is fine:
public static T DoSomething<T>(string typeCode) where T : class, IMovable
{
if (typeCode == "HUM")
{
return new Human() as T; // 'as'
}
else if (typeCode == "ANI")
{
return new Animal() as T; // 'as'
}
else
{
return null;
}
}
Why does as work but explicit cast doesn't?
Short answer is, because T doesn't have to be of the correct type. Compiler is really trying to help you here, because you are doing something which might easily fail in runtime.
E.g. consider what happens with:
var result = DoSomething<Human>("ANI");
Longer answer is, you shouldn't be casting at all. Casting indicates problems with your OOP design, and is especially wrong when using generics: you lose the whole point of generics, actually. Generics are supposed to allow you create a "template" which abstracts away the actual type, leaving you to worry about the algorithm itself instead of concrete types.
In this case, you probably don't need generics at all. Your method is basically a less safer way of doing this:
public static T DoSomething<T>() where T : new()
{
return new T();
}
or this:
public static IMovable DoSomething(string typeCode)
{
if (typeCode == "HUM")
return new Human();
if (typeCode == "ANI")
return new Animal();
return null;
}
To silence the compiler, you may also add an intermediate cast, which tells the compiler you went an extra step to indicate that you really want to cast it this way: For example, using
(T)(object)new Human()
or
(T)(IMovable)new Human()
will both pass compilation, although the conversion from IMovable to T is no safer than the original code, and casting an object to T even unsafer. But this is not the solution to your underlying issue, which is design related.
With your code, it is perfectly possible to call DoSomething<Animal>, and then you have (Animal)new Human().
That is biologically correct, but your model does not allow it.
Do you really need generics here? Maybe you just want to return IMovable in this case.
Under the covers, the 'as' will do an 'is' check first before attempting the cast. So it will not attempt it if it can't cast it and will then return null.
I'm trying to get my head around how type inference is implemented.
In particularly, I don't quite see where/why the heavy lifting of "unification" comes into play.
I'll give an example in "pseudo C#" to help clarify:
The naive way to do it would be something like this:
Suppose you "parse" your program into an expression tree such that it can be executed with:
interface IEnvironment
{
object lookup(string name);
}
interface IExpression
{
// Evaluate this program in this environment
object Evaluate(IEnvironment e);
}
So something like "Multiplication" might be implemented with:
class Multiply : IExpression
{
IExpression lhs;
IExpression rhs;
// etc.
public object Evaluate(IEnvironment e)
{
// assume for the moment C# has polymorphic multiplication
return lhs.Evaluate(e) * rhs.Evaluate(e);
}
}
Then to "implement" type inference, you could just do something like:
interface ITypeEnvironment
{
Type getType(string name);
}
interface IExpression
{
//as before
object Evaluate(IEnvironment e);
// infer type
Type inferType(ITypeEnvironment typeEnvironment);
}
Then "Multiplication"'s type inference might just be something like:
class Multiply : IExpression
{
IExpression lhs;
IExpression rhs;
// ...
public Type inferType(ITypeEnvironment typeEnvironment)
{
Type lhsType = lhs.inferType(typeEnvironment);
Type rhsType = rhs.inferType(typeEnvironment);
if(lhsType != rhsType)
throw new Exception("lhs and rhs types do not match");
// you could also check here that lhs/rhs are one of double/int/float etc.
return lhsType;
}
}
lhs and rhs might be simple constants, or "variables" which are looked up in the environment:
class Constant : IExpression
{
object value;
public Type inferType(ITypeEnvironment typeEnvironment)
{
return value.GetType(); // The type of the value;
}
public object Evaluate(IEnvironment environment)
{
return value;
}
}
class Variable : IExpression
{
string name;
public Type inferType(ITypeEnvironment typeEnvironment)
{
return typeEnvironment.getType(name);
}
public object Evaluate(IEnvironment environment)
{
return environment.lookup(name);
}
}
But nowhere in this do we end up with the need for a "unification" algorithm.
So, clearly, my example is not complex enough. Does it need higher order functions? Do we need "parametric polymorphism"?
What is the simplest possible example where "unification" is actually needed to correctly infer the type of an expression.
An example in Scheme would be ideal (i.e. an example of a very small Scheme program where you require unification to correctly infer the type of the s-expression).
Let me completely ignore your example and give you an example of where we do method type inference in C#. (If this topic interests you then I encourage you to read the "type inference" archive of my blog.)
Consider:
void M<T>(IDictionary<string, List<T>> x) {}
Here we have a generic method M that takes a dictionary that maps strings onto lists of T. Suppose you have a variable:
var d = new Dictionary<string, List<int>>() { ...initializers here... };
M(d);
We have called M<T> without providing a type argument, so the compiler must infer it.
The compiler does so by "unifying" Dictionary<string, List<int>> with IDictionary<string, List<T>>.
First it determines that Dictionary<K, V> implements IDictionary<K, V>.
From that we deduce that Dictionary<string, List<int>> implements IDictionary<string, List<int>>.
Now we have a match on the IDictionary part. We unify string with string, which is obviously all good but we learn nothing from it.
Then we unify List with List, and realize that we have to recurse again.
Then we unify int with T, and realize that int is a bound on T.
The type inference algorithm chugs away until it can make no more progress, and then it starts making further deductions from its inferences. The only bound on T is int, so we deduce that the caller must have wanted T to be int. So we call M<int>.
Is that clear?
public Type inferType(ITypeEnvironment typeEnvironment)
{
return typeEnvironment.getType(name);
}
What if you just don't know the type of the variable? That's the whole point of type inference, right? Something very simple like this (in some pseudocode language):
function foo(x) { return x + 5; }
You don't know the type of x, until you infer the addition, and realize that it must be an integer because it's added to an integer, or something like that.
What if you have another function like this:
function bar(x) { return foo(x); }
You can't figure out the type of x until you have figured out the type of foo, and so on.
So when you first see a variable, you have to just assign some placeholder type for a variable, and then later, when that variable is passed to some kind of function or something, you have to "unify" it with the argument type of the function.
Suppose we have a function
f(x, y)
where x might be e.g. FunctionOfTwoFunctionsOfInteger
or it might be FunctionOfInteger.
suppose we pass in
f(g(u, 2), g(1, z))
Now with unification, u is bound to 1, and z is bound to 2, so the first argument is a FunctionOfTwoFunctionsOfInteger.
So, we have to infer that the type of x and y are both FunctionOfTwoFunctionsOfInteger
I'm not too familiar with C#, but with lambda expressions (or equivalently delegates or whatever) this should probably be possible.
For an example of where type inferencing is very useful in improving the speed of theorem proving, take a look at "Schubert's Steamroller"
http://www.rpi.edu/~brings/PAI/schub.steam/node1.html
There's an issue of the Journal of Automated Reasoning devoted to solutions and formulations to this problem, most of which involve typed inferencing in theorem proving systems:
http://www.springerlink.com/content/k1425x112w6671g0/