Is there a better (more performant or nicer code ;) way to find all derived Types of a Type?
Currently im using something like:
get all types in used Assemblies
check my type with all those types if it is 'IsAssignable'
I was wondering if theres a better way todo this?
I once used this Linq-method to get all types inheriting from a base type B:
var listOfBs = (
from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
// alternative: from domainAssembly in domainAssembly.GetExportedTypes()
from type in domainAssembly.GetTypes()
where typeof(B).IsAssignableFrom(type)
// alternative: && type != typeof(B)
// alternative: && ! type.IsAbstract
// alternative: where type.IsSubclassOf(typeof(B))
select type).ToArray();
EDIT: As this still seems to get more rep (thus more views), let me add a fluent version and some more details:
var listOfBs = AppDomain.CurrentDomain.GetAssemblies()
// alternative: .GetExportedTypes()
.SelectMany(domainAssembly => domainAssembly.GetTypes())
.Where(type => typeof(B).IsAssignableFrom(type)
// alternative: => type.IsSubclassOf(typeof(B))
// alternative: && type != typeof(B)
// alternative: && ! type.IsAbstract
).ToArray();
Details:
As the above-mentioned link states, this method uses Reflection on each call. So when using the method repeatedly for the same type,
one could probably make it much more efficient by loading it once.
As Anton suggests, maybe you could (micro)optimize it using domainAssembly.GetExportedTypes()
to retrieve only publicly visible types (if that's all you need).
As Noldorin mentions, Type.IsAssignable will also get the original (non-derived) type. (Type.IsSubclassOf will not, but Type.IsSubclassOf will not work if the base type is an interface). But of course, one can exclude the original base class: && type != typeof(B).
One may want/need to check for a concrete implemented class, i.e. ignore abstract classes: && ! assemblyType.IsAbstract. (Note that all interfaces are considered abstract, see MSDN.)
FWIW: as Jon Skeet suggested in a similar question: "it is trickier if you need to handle generics".
A quick search returns some suggestions, but there are probably more, and I did not check them (e.g. for correctness):
Get all types implementing specific open generic type
Get all implementations types of a generic interface
Getting all types that implement an interface
I'm pretty sure the method you suggested is going to be the easier way to find all derived types. Parent classes don't store any information about what their sub-classes are (it would be quite silly if they did), which means there's no avoiding a search through all the types here.
Only recommendation is to use the Type.IsSubclassOf method instead of Type.IsAssignable in order to check whether a particular type is derived from another. Still, perhaps there is a reason you need to use Type.IsAssignable (it works with interfaces, for example).
The only optimization you can squeeze out of this is to use Assembly.GetExportedTypes() to retrieve only publicly visible types if that's the case. Other than that, there's no way to speed things up. LINQ may help with readability side of things, but not performance-wise.
You can do some short-circuiting to avoid unnecessary calls to IsAssignableFrom which is, according to Reflector, quite expensive one, by first testing whether the type in question is of required "class". That is, you're searching for classes only, there's no point in testing enums or arrays for "assignability".
I think there is no better or direct way.
Better: Use IsSubclassOf instead of IsAssignable.
Asuming baseType contains a System.Type object that you want to check against and matchType contains a System.Type object with the type of your current iteration (through a foreach-loop or whatever):
If you want to check wheather matchType is derived from the class represented by baseType I'd use
matchType.IsSubclassOf(baseType)
And if you want to check wheather matchType implements the interface represented by baseType I'd use
matchType.GetInterface(baseType.ToString(), false) != null
Of course I'd store baseType.ToString() as a global variable so I wouldn't need to call it all the time. And since you probably would need this in a context where you have a lot of types, you could also consider using the System.Threading.Tasks.Parallel.ForEach-Loop to iterate through all your types...
If you're just interested in browsing, then .NET Reflector has the ability to do this. However, it isn't something that's really feasible. Would you want all types that are in the currently loaded assemblies? Assemblies referenced by the executing assembly? There are many different ways to obtain a list of Types, and writing something that would account for (and provide options for) would be a pretty big cost with relatively low benefit.
What are you trying to do? There's likely a better (or at least more efficient) way to accomplish it.
I ended up using the code that the top answer gave. Only thing is I wanted the code to be more readable so I wrote basically the same thing but like this instead:
var derived_types = new List<Type>();
foreach (var domain_assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var assembly_types = domain_assembly.GetTypes()
.Where(type => type.IsSubclassOf(typeof(MyType)) && !type.IsAbstract);
derived_types.AddRange(assembly_types);
}
In my case I used type.IsSubClassOf(MyType) because I only wanted derived types excluding the base class like mentioned above. I also needed the derived types not to be abstract (!type.IsAbstract) so I am also excluding derived abstract classes.
Just create a static dictionary of derived types on start and do lookup with that.
Eg. public static Dictionay<Type, Type[]> DerivedTypes { get;set; }
where Type is any type you want to include in the search
and Type[] is a list of derived types.
Fill the dictionary up when app starts and use it during the whole life of the app.
Related
Okay. I'll be brief. Why doesn't this work ?
//Find<T> returns the T object with a given name
//Not a true method, but that's simplier for the example.
Warrior conan = Find<Warrior> ("Conan");
//Debug.Log is just printing the results
Debug.Log (conan is Warrior); //True
Debug.Log (conan is Character); //True, Warrior extends Character
Character other = Find<Character> ("Conan"); // Null, Why ?
I guess that generic c# methods are quite differents in IL, and this is why that doesn't work. But it's quite annoying. Am I doing anything wrong ? Is there a way to bypass this ?
EDIT:
In fact, my method is a bit different. I'm using MVC and I want to find the view corresponding to a model.
public ElementView<E> Find<E> (E model) {
ElementView<E>[] tab = gameBoardView.transform.GetComponentsInChildren<ElementView<E>> ();
foreach (ElementView<E> el in tab)
if (EqualityComparer<E>.Default.Equals(el.model, model))
return el;
return null;
}
And I use it like this :
ElementView<Warrior> w = Find<Warrior> (myCharacter); // good if my character is a warrior
ElementView<Character> c = Find<Character> (myCharacter); // null
As noted in the comments, you could probably answer this question yourself, if you would study variance in generic type parameters. Recommended reading includes:
In C#, why can't a List object be stored in a List variable
C# variance problem: Assigning List as List
Contravariance explained
Difference between Covariance & Contra-variance
Eric Lippert's Wizards and warriors series (this link is to part 1)
That said, in an effort to address your immediate concern and to possibly provide some practical, actionable information…
Your method breaks here:
ElementView<E>[] tab = gameBoardView.transform.GetComponentsInChildren<ElementView<E>> ();
Specifically, the type of the model is Warrior, which will have an instance of ElementView<Warrior> in the collection being searched by GetComponentsInChildren<T>(). When you call Find<Character>(), you call the generic method GetComponentsInChildren<Character>(), which will search for instances of ElementView<Character>.
Since ElementView<Warrior> is not an ElementView<Character> — that is, it doesn't inherit that type — it is excluded from the search. The search would return only instances of ElementView<Character>, which will not include the view for the model in question. (The returned collection may in fact be empty, if Character is simply the base class used by all of the real types…only if there are actual ElementView<Character> objects in the components collection would you even get any objects returned by the method.)
Whether you can do anything about this depends on the type ElementView<T> and whether you are able to introduce an interface type into your code to represent ElementView<T> objects. That is, it would be legal for GetComponentsInChildren<T>() to return objects of type ElementView<Warrior> when you ask for objects of type ElementView<Character> only if:
You can change the code to return a collection of interface types instead of ElementView<T> types (e.g. IElementView<T>), and
The interface's type parameter T can be declared as covariant; that is, with the out keyword, indicating that all members of the interface only ever return objects of type T, and not accept them as parameters.
If those things were true, then you could declare the appropriate interface, make sure that ElementView<T> implements that interface, and then objects of type ElementView<Warrior> could be cast to the interface type IElementView<Character>. Since the interface type parameter would be Character, and the interface implementation could only return objects of type Character, the fact that the object is actually returning an object of type Warrior would be fine. Warrior is (presumably) a Character, and so returning a Warrior satisfies the interface's declaration of returning Character values.
If you could meet those requirements, then the GetComponentsInChildren<T>() method could return an array of type IElementView<T>[], which could in fact contain your object of interest that is actually type ElementView<U> where U inherits T (i.e. GetComponentsInChildren<Character>() would return IElementView<Character>[], in which it would be valid to find an instance of IElementView<Warrior>).
Of course, you'd also need to change the code that uses these types, including GetComponentsInChildren<T>() (depending on its implementation). It's not a simple "throw the switch" kind of change to support variance in your generic types. But assuming your types are compatible with variant declarations, it can be a worthwhile effort.
I can't provide any specific advice on how exactly those changes would be made, or even if they are possible, since your question does not include a good Minimal, Complete, and Verifiable code example. If you want to make these changes, I recommend you study variance first, then make an effort on your own to change the code. If you still have trouble after that, post a new question, being sure to include a good MCVE showing clearly what you're trying to do, and explain precisely what it is you're still having trouble with.
What is the design decision to lean towards not returning an anonymous types from a method?
You can return an instance of an anonymous type from a method - but because you can't name it, you can't declare exactly what the method will return, so you'd have to declare that it returns just object. That means the caller won't have statically typed access to the properties etc - although they could still pass the instance around, access it via reflection (or dynamic typing in C# 4).
Personally I would quite like a future version of C# to allow you to write a very brief class declaration which generates the same code (immutable properties, constructor, Equals/GetHashcode/ToString) with a name...
There is one grotty hack to go round it, called casting by example. I wouldn't recommend it though.
Because an anonymous type has no name. Therefore you cannot declare a return type for a method.
Because C# is statically typed language and in a statically typed language the return type of a method needs to be known at compile time and anonymous types have no names.
How can you use your type inside your method if the definition is only in the call of the method ?
It's not javascript.
A lot of answers heere seem to indicatie that it is not possible because of the current syntax and rule. But the question is about changing them. I think it would be possible, but a little complicated and resulting in an awkward (error-prone) syntax. Like
var f() { return new { A = "*", B = 1 }; }
var x = f();
The question is whether this adds sufficient value to the language to make it worth it.
At least up to 3.5, anonymous types are actually resolved at compile time, and this would be impossible (or quite hard) to do with anonymous method signatures.
I thought i've seen it all but this... :)
I was working on a generic graph of type string,
Graph<string> graph = new Graph<string>();
Graph is declared with a class constraint like this:
public class Graph<T> where T : class
Next i fill up the graph with some dynamicly generated strings:
for (char t = 'A'; t < 'J'; t++)
{
GraphPrim.Add(t.ToString());
}
So far so good, (Node is a internal class containing the original value and a list of references to other nodes (because its a graph))
Now, when i try to create relations between the different nodes, i have to look up the right node by checking its value and thats where the weirdness starts.
The following code, is a direct copy of the result found in the immidiate window after doing some tests:
Nodes.First().Value
"A"
Nodes.First().Value == "A"
false
Nodes.First().Value.ToString() == "A"
true
Am i totally missing something or shouldn't Nodes.First().Value == "A" use a string comparison method. (The JIT compiler has knowledge about the type beeing used on runtime, and with that, its supported methods, right?). It seems to me like when not explicitly specifying a string, it will do a reference check rather then a string test.
It would be great if someone could explain this to me,
Thanks in advance!
If the types aren't fully known up front (i.e. Value is only known as T, and is not strictly known to be a string), use things like:
object.Equals(Nodes.First().Value,"A")
Of course, you could cast, but in this case you'd need a double-cast ((string)(object)) which is ugly.
If you know the two objects are the same type (i.e. two T values), then you can use:
EqualityComparer<T>.Default.Equals(x,y)
The advantage of the above is that it avoids boxing of structs and supports lifted Nullable<T> operators, and IEquatable<T> in addition to Equals.
If the Value property of your Nodes is object, the == operator in
Nodes.First().Value == "A"
will do a comparison by reference instead of comparing strings.
== is a static method and therefore not virtual. The selection of which == method to use is done at compile-time, not run-time. Depending on the compile-time type of the object, it is probably choosing the implementation of == for objects that compares by reference.
If you use the virtual Equals methods instead, this will work as you expect.
This is harder to find in the docs than I imagined. Anyway, I have some instances of Type. How can I find out if they represent classes, methods, interfaces, etc?
class Bla { ... }
typeof(Bla).GetKindOrWhatever() // need to get something like "Class"
(I'm using Mono on Linux but that shouldn't affect the question, I'm making portable code)
Type.IsClass might help here. Also Type.IsInterface.
Check out...
http://msdn.microsoft.com/en-us/library/system.type_members.aspx
There are quite a few "IsXxxx" properties on Type. Hopefully these will do what you want.
By the way, you should check out other questions on this subject on SO, including this one...
typeof(System.Enum).IsClass == false
... if the types you're going to be checking are enum types, as there are some strange (but predictable) results.
There are a slew of properties off the Type class.
typeof(Bla).IsClass
typeof(Bla).IsInterface
etc.
http://msdn.microsoft.com/en-us/library/system.type_properties.aspx
The Type class have some properties that are named IsXXX.
For example it has a IsEnum, IsClass, IsInterface.
If I understand correctly your question this is what you need
As others have mentioned, the Type class has various properties that you can use if you just need to know whether your type is a class, interface, delegate, etc.
If you have a Type object and you want to know if it is a specific type, then I recommend using the IsAssignableFrom method found on the Type class:
Type objectType = obj.GetType();
Type interfaceType = typeof(IExample);
if (interfaceType.IsAssignableFrom(objectType))
{
//...
}
Type.IsClass Property?
Is there a better (more performant or nicer code ;) way to find all derived Types of a Type?
Currently im using something like:
get all types in used Assemblies
check my type with all those types if it is 'IsAssignable'
I was wondering if theres a better way todo this?
I once used this Linq-method to get all types inheriting from a base type B:
var listOfBs = (
from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
// alternative: from domainAssembly in domainAssembly.GetExportedTypes()
from type in domainAssembly.GetTypes()
where typeof(B).IsAssignableFrom(type)
// alternative: && type != typeof(B)
// alternative: && ! type.IsAbstract
// alternative: where type.IsSubclassOf(typeof(B))
select type).ToArray();
EDIT: As this still seems to get more rep (thus more views), let me add a fluent version and some more details:
var listOfBs = AppDomain.CurrentDomain.GetAssemblies()
// alternative: .GetExportedTypes()
.SelectMany(domainAssembly => domainAssembly.GetTypes())
.Where(type => typeof(B).IsAssignableFrom(type)
// alternative: => type.IsSubclassOf(typeof(B))
// alternative: && type != typeof(B)
// alternative: && ! type.IsAbstract
).ToArray();
Details:
As the above-mentioned link states, this method uses Reflection on each call. So when using the method repeatedly for the same type,
one could probably make it much more efficient by loading it once.
As Anton suggests, maybe you could (micro)optimize it using domainAssembly.GetExportedTypes()
to retrieve only publicly visible types (if that's all you need).
As Noldorin mentions, Type.IsAssignable will also get the original (non-derived) type. (Type.IsSubclassOf will not, but Type.IsSubclassOf will not work if the base type is an interface). But of course, one can exclude the original base class: && type != typeof(B).
One may want/need to check for a concrete implemented class, i.e. ignore abstract classes: && ! assemblyType.IsAbstract. (Note that all interfaces are considered abstract, see MSDN.)
FWIW: as Jon Skeet suggested in a similar question: "it is trickier if you need to handle generics".
A quick search returns some suggestions, but there are probably more, and I did not check them (e.g. for correctness):
Get all types implementing specific open generic type
Get all implementations types of a generic interface
Getting all types that implement an interface
I'm pretty sure the method you suggested is going to be the easier way to find all derived types. Parent classes don't store any information about what their sub-classes are (it would be quite silly if they did), which means there's no avoiding a search through all the types here.
Only recommendation is to use the Type.IsSubclassOf method instead of Type.IsAssignable in order to check whether a particular type is derived from another. Still, perhaps there is a reason you need to use Type.IsAssignable (it works with interfaces, for example).
The only optimization you can squeeze out of this is to use Assembly.GetExportedTypes() to retrieve only publicly visible types if that's the case. Other than that, there's no way to speed things up. LINQ may help with readability side of things, but not performance-wise.
You can do some short-circuiting to avoid unnecessary calls to IsAssignableFrom which is, according to Reflector, quite expensive one, by first testing whether the type in question is of required "class". That is, you're searching for classes only, there's no point in testing enums or arrays for "assignability".
I think there is no better or direct way.
Better: Use IsSubclassOf instead of IsAssignable.
Asuming baseType contains a System.Type object that you want to check against and matchType contains a System.Type object with the type of your current iteration (through a foreach-loop or whatever):
If you want to check wheather matchType is derived from the class represented by baseType I'd use
matchType.IsSubclassOf(baseType)
And if you want to check wheather matchType implements the interface represented by baseType I'd use
matchType.GetInterface(baseType.ToString(), false) != null
Of course I'd store baseType.ToString() as a global variable so I wouldn't need to call it all the time. And since you probably would need this in a context where you have a lot of types, you could also consider using the System.Threading.Tasks.Parallel.ForEach-Loop to iterate through all your types...
If you're just interested in browsing, then .NET Reflector has the ability to do this. However, it isn't something that's really feasible. Would you want all types that are in the currently loaded assemblies? Assemblies referenced by the executing assembly? There are many different ways to obtain a list of Types, and writing something that would account for (and provide options for) would be a pretty big cost with relatively low benefit.
What are you trying to do? There's likely a better (or at least more efficient) way to accomplish it.
I ended up using the code that the top answer gave. Only thing is I wanted the code to be more readable so I wrote basically the same thing but like this instead:
var derived_types = new List<Type>();
foreach (var domain_assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var assembly_types = domain_assembly.GetTypes()
.Where(type => type.IsSubclassOf(typeof(MyType)) && !type.IsAbstract);
derived_types.AddRange(assembly_types);
}
In my case I used type.IsSubClassOf(MyType) because I only wanted derived types excluding the base class like mentioned above. I also needed the derived types not to be abstract (!type.IsAbstract) so I am also excluding derived abstract classes.
Just create a static dictionary of derived types on start and do lookup with that.
Eg. public static Dictionay<Type, Type[]> DerivedTypes { get;set; }
where Type is any type you want to include in the search
and Type[] is a list of derived types.
Fill the dictionary up when app starts and use it during the whole life of the app.