简体   繁体   English

C# 非通用 ISet 接口

[英]C# Non-Generic ISet Interface

.NET 4.0 introduced a non-generic IList which exposes the ability to add values to the List without needing to know the generic type. .NET 4.0引入了一个非泛型IList ,它公开了向 List 添加值的能力,而无需知道泛型类型。 This is useful because it allows me to write a method such as the following:这很有用,因为它允许我编写如下方法:

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;
}

However, when I try to implement a method with a similar style for HashSet or ISet , there is not such non-generic interface I can find that exposes and Add() method.但是,当我尝试为HashSetISet实现一个具有类似样式的方法时,我找不到这样的非通用接口来公开和Add()方法。

I am wondering if such an interface exists that I may have missed.我想知道是否存在我可能错过的这样的界面。 If not, I am wondering how I can go about adding elements to object I know for certain is Set (since I created it the Activator.CreateInstance() )如果没有,我想知道如何将元素添加到我确定是Set对象中(因为我创建了它Activator.CreateInstance()

I would end up with a couple of aux types for constructing a set:我最终会得到几个用于构建集合的辅助类型:

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;
}

Those types then could be used like this:然后可以像这样使用这些类型:

var builderType = typeof(SetBuilder<,>).MakeGenericType(elementType, outputType);
var builder = (ISetBuilder) Activator.CreateInstance(builderType);
var element = CreateElement(...);
builder.Add(element);
var set = builder.Build();

And yes, this could be generalised to support lists as well.是的,这也可以推广到支持列表。 Just replace ISet<T> with ICollection<T> .只需将ISet<T>替换为ICollection<T>

Another possible (but a bit less robust) solution is just to find and call the specific Add method of a set by using reflection.另一种可能(但不太稳健)的解决方案是通过使用反射来查找和调用集合的特定Add方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM