C# 非通用 ISet 接口
C# Non-Generic ISet Interface
.NET 4.0
引入了一个非泛型 IList
,它公开了在不需要知道泛型类型的情况下向列表添加值的能力。这很有用,因为它允许我编写如下方法:
void CreateListFromBytes(IntPtr bytes, Type outputType, out object outputObject)
{
Type elementType = outputType.GenericTypeArguments[0];
int numberOfElements = ReadHeaderBytes(bytes);
bytes += Marshal.SizeOf(typeof(int));
IList outputList = (IList) Activator.CreateInstance(outputType);
for (int i = 0; i < numberOfElements; i++)
{
object element = ReadDataBytes(bytes, elementType);
bytes += Marshal.SizeOf(elementType);
outputList.Add(element);
}
outputObject = outputList;
}
但是,当我尝试为 HashSet
或 ISet
实现具有类似风格的方法时,我找不到这样的非通用接口,我发现它公开了 Add()
方法。
我想知道是否存在我可能错过的这样的界面。如果不是,我想知道如何将元素添加到我确定是 Set
的对象(因为我创建它是 Activator.CreateInstance()
)
我最终会得到几个用于构建集合的辅助类型:
interface ISetBuilder
{
void Add(object item);
object Build();
}
class SetBuilder<T, TSet> : ISetBuilder where TSet : ISet<T>, new()
{
private readonly TSet _set = new TSet();
public void Add(object item)
{
if (!(item is T typedItem))
{
throw new ArgumentException();
}
_set.Add(typedItem);
}
public object Build() => _set;
}
这些类型可以这样使用:
var builderType = typeof(SetBuilder<,>).MakeGenericType(elementType, outputType);
var builder = (ISetBuilder) Activator.CreateInstance(builderType);
var element = CreateElement(...);
builder.Add(element);
var set = builder.Build();
是的,这也可以推广到支持列表。只需将 ISet<T>
替换为 ICollection<T>
.
另一种可能(但不太健壮)的解决方案是使用反射找到并调用集合的特定 Add
方法。
.NET 4.0
引入了一个非泛型 IList
,它公开了在不需要知道泛型类型的情况下向列表添加值的能力。这很有用,因为它允许我编写如下方法:
void CreateListFromBytes(IntPtr bytes, Type outputType, out object outputObject)
{
Type elementType = outputType.GenericTypeArguments[0];
int numberOfElements = ReadHeaderBytes(bytes);
bytes += Marshal.SizeOf(typeof(int));
IList outputList = (IList) Activator.CreateInstance(outputType);
for (int i = 0; i < numberOfElements; i++)
{
object element = ReadDataBytes(bytes, elementType);
bytes += Marshal.SizeOf(elementType);
outputList.Add(element);
}
outputObject = outputList;
}
但是,当我尝试为 HashSet
或 ISet
实现具有类似风格的方法时,我找不到这样的非通用接口,我发现它公开了 Add()
方法。
我想知道是否存在我可能错过的这样的界面。如果不是,我想知道如何将元素添加到我确定是 Set
的对象(因为我创建它是 Activator.CreateInstance()
)
我最终会得到几个用于构建集合的辅助类型:
interface ISetBuilder
{
void Add(object item);
object Build();
}
class SetBuilder<T, TSet> : ISetBuilder where TSet : ISet<T>, new()
{
private readonly TSet _set = new TSet();
public void Add(object item)
{
if (!(item is T typedItem))
{
throw new ArgumentException();
}
_set.Add(typedItem);
}
public object Build() => _set;
}
这些类型可以这样使用:
var builderType = typeof(SetBuilder<,>).MakeGenericType(elementType, outputType);
var builder = (ISetBuilder) Activator.CreateInstance(builderType);
var element = CreateElement(...);
builder.Add(element);
var set = builder.Build();
是的,这也可以推广到支持列表。只需将 ISet<T>
替换为 ICollection<T>
.
另一种可能(但不太健壮)的解决方案是使用反射找到并调用集合的特定 Add
方法。