我有以下代码:
public class SampleClass<T, TCollection> where TCollection : class, IList<T>, IReadOnlyList<T>
{
private readonly TCollection _collection;
public SampleClass() : this(new List<T>()) { }
public SampleClass(TCollection collection)
{
_collection = collection;
}
}
不幸的是,包含默认构造函数public SampleClass() : this(new List<T>()) { }
的行无法编译。错误消息显示:参数1:无法转换为&#39; System.Collections.Generic.List&#39;到&#39; TCollection&#39; 。
为什么会这样? List<T>
实际上符合我对TCollection泛型的所有限制:它是一个实现IList<T>
和IReadOnlyList<T>
的类。
非常感谢你的帮助。
编辑:更新了代码,因为它包含错误。
答案 0 :(得分:5)
为什么会这样?
问题是我可以编写这样的代码:
class X : IList<int>, IReadOnlyList<int>
{
...
}
然后尝试使用它:
var instance = new SampleClass<int, X>();
但是没有从List<int>
转换为X
。
此方案的可能性是您收到编译器错误消息的原因:
参数1:无法转换为System.Collections.Generic.List&#39;到&#39; TCollection&#39;。
获取List<T>
&#34;的默认值您正在寻找的行为,您可以摆脱该默认构造函数并将其替换为以下内容:
static class SampleClass
{
public static SampleClass<T, List<T>> Create<T>()
{
return new SampleClass<T, List<T>>(new List<T>());
}
}
这是一种类似于Tuple
静态类及其静态Tuple.Create
泛型方法和非静态Tuple<T1>
,Tuple<T1, T2>
等类的模式。
答案 1 :(得分:1)
您的方法存在的问题是,您假设您可以将List<T>
分配给TCollection
类型的引用,而实际上并不知道TCollection
是什么。您可以在这里使用两种方法。前者更接近你现在拥有的,而后者允许你编写一个更容易在更广泛的场景中使用的类。
对new
使用TCollection
约束。虽然你还不知道TCollection
是什么类型,但编译器要求类型有一个默认构造函数,允许你写这个:
public class SampleClass<T, TCollection>
where TCollection : IList<T>, IReadOnlyList<T>, new()
{
public SampleClass() : this(new TCollection()) { }
public SampleClass(TCollection collection) { ... }
}
要求在TCollection
的实例中调用代码,而不是自己创建。在这种情况下,您只需删除默认构造函数。
答案 2 :(得分:1)
将通用约束更改为TCollection
并添加new()
约束。然后,您可以使用new TCollection()
public class SampleClass<T, TCollection> where TCollection : class, IList<T>, IReadOnlyList<T>, new()
{
private readonly TCollection _collection;
public SampleClass() : this(new TCollection()) { }
public SampleClass(TCollection collection)
{
_collection = collection;
}
}
答案 3 :(得分:1)
我相信Sam Harwell有部分答案,你真的希望TCollection
成为包含T
元素的东西,所以你应该有:
public class SampleClass<T, TCollection>
where TCollection : class, IList<T>, IReadOnlyList<T>
但是,这还不足以处理这样一个事实,即你想要一个无参数构造函数将new List<T>()
传递给带有TCollection
参数的构造函数。有些东西可能是TCollection
而不是List<T>
或其基础,因此没有足够的约束来保证这可以起作用。
有三种可能的方法。一,完全摆脱无参数构造函数:
public class SampleClass<T, TCollection> where TCollection : class, IList<T>, IReadOnlyList<T>, new()
{
private readonly TCollection _collection;
public SampleClass(TCollection collection)
{
_collection = collection;
}
}
两,将传入的集合存储为List<T>
,并坚持TCollection
为它或从中派生(不太可能有用):
public class SampleClass<T, TCollection> where TCollection : List<T>
{
private readonly List<T> _collection;
public SampleClass() : this(new List<T>()) { }
public SampleClass(TCollection collection)
{
_collection = collection;
}
}
三,坚持TCollection
是一个带无参数构造函数的类,并使用它:
public class SampleClass<T, TCollection> where TCollection : class, IList<T>, IReadOnlyList<T>, new()
{
private readonly TCollection _collection;
public SampleClass() : this(new TCollection()) { }
public SampleClass(TCollection collection)
{
_collection = collection;
}
}
答案 4 :(得分:0)
TCollection
是您定义的类吗?
List<T>
实现:
public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>,
IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
TCollection
是否实施IList
,ICollection
或继承List<T>
或Collection<T>
的基类?您的TCollection
必须实现或继承其中一个以删除编译错误。
您还需要将班级TCollection
更改为TCollection<T>
才能接受通用定义的new List<T>
。通用需要在某处传递给您的集合。
除非您将约束放在定义TCollection
的位置上。您可能需要注意的是,您对通用<T>
而不是TCollection
设置了约束。