问题
I'm trying to simplify my methods in creating several variables in a function which is repeated for different types and different actions, eventually I will migrate to a single function that can handle multiple types but I'm doing it in stages. I would like to be able to make a list of objects in their types instead of List without having to copy/paste the object type everywhere. I had hoped to accomplish this by something really simple like
Type t = typeof(LinkAddy);
var x = List<t>();
but this doesn't compile.
Then I tried a different solution provided by the following answer: Storing variable type and using it to create collections at runtime
static IList createGenericList(Type typeInList) {
var genericListType = typeof(List<>).MakeGenericType(new[] { typeInList });
return (IList)Activator.CreateInstance(genericListType);
}
and
static List<T> createGenericList<T>() {
List<T> genericListType = new List<T>();
return genericListType;
}
So here's the different methods and their results:
Type ThisType = typeof(LinkAddy);
// The normal list method, means I have to copy/paste LinkAddy everywhere
var fromQuery = new List<LinkAddy>();
// Makes a List, but I still have to put LinkAddy
var fromQuery_IsNew = createGenericList<LinkAddy>();
// Provides a List, I don't have to place LinkAddy
// but its a List<object> and not List<LinkAddy> so wherever I use
// the objects, I'll have to cast the object like
// string title = (fromQuery_IsDiff[0] as LinkAddy).Title;
var fromQuery_IsDiff = createGenericList(ThisType);
Edit: Eventually, I won't know the type at runtime, the function would be made generic so I could pass LinkAddy as a type or some other type and it would generate the lists as needed. The first step is just to have generics all throughout the function and do is checks on the type for anything that needs to be more specific. This is part of a large function that covers about 200 lines of code that has to do with list validation checks for a database sync (it determines which of the cached and server versions are newer and whichever is newer, post an overwrite to the other if you have permissions to do so). I have multiple classes similar to LinkAddy that are sync using WCF RIA services and SilverLight to a SQL database on the server. The entries are also stored in a class that does XML serialization and saves the XML file to the user's system (cached). This allows my agents in the field to have access to the majority of my site data without an internet connection, as is often the case for them in front of customers.
回答1:
It's not really clear how you expect this could possibly work, especially given the comment:
// Provides a List, I don't have to place LinkAddy
// but its a List<object> and not List<LinkAddy> so wherever I use
// the objects, I'll have to cast the object like
// string title = (fromQuery_IsDiff[0] as LinkAddy).Title;
If you know enough to cast to LinkAddy
(which would be better done as a cast than using as
, IMO) then you clearly know the type at compile time. If you know the type at compile-time, just supply it as a type argument.
Things like MakeGenericType
are useful when you don't know the type involved at compile-time, which means you can't cast... and you can't use any of the other things you know about the type anyway.
You could potentially use dynamic typing instead... but if you know that there will be a Title
property, perhaps what you really want is an interface instead, expressing the commonality. Then you could potentially use generic methods which have a constraint on that interface.
Anyway, you should think about which things you know at compile-time and which things are only known at execution time. For the most part, generics is aimed at types known at compile-time... while using generics at execution time via reflection is possible, it's sort of fighting against the design, so you shouldn't be surprised when it's frustrating.
来源:https://stackoverflow.com/questions/15398543/create-list-of-type-using-type-variable-at-runtime