我想做这样的事情:
public List<T> GetList<T>()
{
if (typeof(T) == typeof(Type1))
{
return new List<Type1>() { new Type1(), new Type1(), new Type1() };
}
if (typeof(T) == typeof(Type2))
{
return new List<Type2>() {new Type2(), new Type2()};
}
throw new Exception("Unknown T");
}
public void DoStuffWithGenericList<T>()
{
var list = GetList<T>();
// do stuff that does not depend on T
}
但是,这当然不合法。我觉得我错过了一些基本的东西:)
就我而言,我从Entity Framework获取不同类型对象的列表,但我的其余逻辑并不依赖于实际类型。它可以在List上工作,也可以是通用的。
将使用类型参数调用GetList()的所有Ts将从相同的基类继承,如果它有所不同。
答案 0 :(得分:6)
为什么不使用'new'运算符来实例化类型:
public List<T> GetList<T>() where T : new()
{
if (typeof(T) == typeof(Type1))
{
return new List<T>() { new T() };
}
// etc...
throw new Exception("Unknown T");
}
您所要做的就是确保通过添加new()约束来实例化您的类型。
答案 1 :(得分:4)
这样的代码无法工作,因为它取决于运行时类型检查(您已明确写入它们)。但编译器如何知道在编译时运行时检查的结果实际上是List<T>
?
在这个具体的例子中,你可以用
达到预期的目标public List<T> GetList<T>() where T : new()
{
if (typeof(T) == typeof(Type1))
{
return new List<T>() { new T(), new T(), new T() };
}
if (typeof(T) == typeof(Type2))
{
return new List<T>() { new T(), new T() };
}
throw new Exception("Unknown T");
}
但当然这并没有解决任何实际问题。如果你有任何具体的问题而不是“为什么这不起作用”,你应该编辑问题来呈现它。
考虑一下:要在代码中的某个位置使用GetList
,您需要编写
var x = GetList<SomeType>();
类型参数SomeType
必须在调用站点进行硬编码,否则程序将无法编译。但如果它必须是硬编码的,那么上述内容与
public List<SomeType> GetListOfSomeType()
{
return new List<SomeType>();
}
var x = GetListOfSomeType();
那么你想要完成什么呢?
当然,这个反例也有点肤浅,实际上GetList
的通用版本如果你愿意使用反射,会增加灵活性。但同样,在你的例子中并非如此。
答案 2 :(得分:3)
public List<T> GetList<T>()
{
if (typeof(T) == typeof(Type1))
{
return new List<Type1>() { new Type1(), new Type1(), new Type1() }.Cast<T>().ToList();
}
if (typeof(T) == typeof(Type2))
{
return new List<Type2>() {new Type2(), new Type2()}.Cast<T>().ToList();
}
throw new Exception("Unknown T");
}
答案 3 :(得分:0)
只需转换返回值,因为您已经检查过以确保类型正确:
return (List<T>)(object)new List<Type1>(...
答案 4 :(得分:0)
每当我要看if(typeof(T) == typeof(SomeType)
时,我都会切换到一个看起来或多或少的字典:
public static class ListCreator
{
private static readonly Dictionary<Type, Func<object>> _Creators;
static ListCreator()
{
_Creators = new Dictionary<Type, Func<object>>();
InitializeDefaultCreators();
}
public static List<T> Create<T>()
{
Func<object> creator;
if (!_Creators.TryGetValue(typeof(T), out creator))
{
throw new InvalidOperationException("No creator available for type " + typeof(T).FullName);
}
return (List<T>)creator();
}
public static void Register<T>(Func<List<T>> creator)
{
_Creators.Add(typeof(T), creator);
}
public static void Register(Type type, Func<object> creator)
{
_Creators.Add(type, creator);
}
public static bool Unregister<T>()
{
return _Creators.Remove(typeof(T));
}
public static bool Unregister(Type type)
{
return _Creators.Remove(type);
}
private static void InitializeDefaultCreators()
{
Register(MyDoubleListCreator);
Register(typeof(int), () => Enumerable.Range(1, 15).ToList());
}
private static List<double> MyDoubleListCreator()
{
return Enumerable.Range(1, 10).Select(Convert.ToDouble).Select(val => val + 0.3).ToList();
}
}
这可以通过以下方式使用:
internal class Program
{
private static void Main(string[] args)
{
ListCreator.Register(SelfMadeList);
var someIntegers = ListCreator.Create<int>();
foreach (var item in someIntegers)
{
Console.WriteLine("Some integer: " + item);
}
var someDoubles = ListCreator.Create<double>();
foreach (var item in someDoubles)
{
Console.WriteLine("Some doubles: " + item);
}
var someTimeSpans = ListCreator.Create<TimeSpan>();
foreach (var item in someTimeSpans)
{
Console.WriteLine("Some timespans: " + item);
}
Console.ReadKey();
}
private static List<TimeSpan> SelfMadeList()
{
return Enumerable.Range(1, 20)
.Select(Convert.ToDouble)
.Select(val => val + 0.5)
.Select(TimeSpan.FromHours)
.ToList();
}
}
答案 5 :(得分:-1)
如果类型不是从公共类派生的,则可以返回List<Object>
,然后在使用它们时转换单个元素。