Можно ли создать коллекцию общих ограниченных типов в .net? - PullRequest
0 голосов
/ 20 января 2010

Возможно ли что-то подобное?

Dim l As New List(Of T As Type Where GetType(BaseClass).IsAssignableFrom(T))

Обратите внимание, моя коллекция будет коллекцией типов, а не объектов типа T - что, я знаю, возможно.

ETA:

Ответы, которые у меня были до сих пор, такие же, как и ожидалось - я не думал, что это возможно.

Я пытаюсь понять, почему следующее может быть решено при компиляциивремя, но не мой пример:

Dim l as New List(Of T As BassClass)

Чеки, по сути, не одинаковы?

Ответы [ 6 ]

2 голосов
/ 20 января 2010

Проверки не совпадают - в первом примере вы просите компилятор вызвать метод IsAssignableFrom, а затем сделать что-то на основе результата.Во втором примере вы просите статическую проверку типов компилятора выполнить некоторую работу.

В общем, компилятор не вызывает произвольный код во время компиляции.

А также помните,любые ограничения типов на универсальные элементы должны быть встроены в метаданные ваших сборок.И снова, вы не можете поместить произвольный код в ограничение общего типа.

2 голосов
/ 20 января 2010

У вас может быть принудительное ограничение времени выполнения для вашей коллекции, например:

public class ConstrainedTypeCollection<TBaseType> : Collection<Type>
{
    protected override void InsertItem(int index, Type item)
    {
        if (!typeof(TBaseType).IsAssignableFrom(item))
            throw new ArgumentException("The type is incompatible.", "item");

        base.InsertItem(index, item);
    }

    protected override void SetItem(int index, Type item)
    {
        if (!typeof(TBaseType).IsAssignableFrom(item))
            throw new ArgumentException("The type is incompatible.", "item");

        base.SetItem(index, item);
    }
}

Изменить: Вы также можете сделать следующее и получить полную безопасность типов во время компиляции, если вы вызываете универсальные методы Add<T>(), Contains<T>() и Remove<T>().

public class ConstrainedTypeCollection<TBaseType> : ICollection<Type>
{
    private readonly List<Type> _collection = new List<Type>();

    public void Add<T>()
        where T : TBaseType
    {
        _collection.Add(typeof(T));
    }

    public bool Contains<T>()
        where T : TBaseType
    {
        return _collection.Contains(typeof(T));
    }

    public bool Remove<T>()
        where T : TBaseType
    {
        return _collection.Remove(typeof(T));
    }

    public int Count
    {
        get
        {
            return _collection.Count;
        }
    }

    bool ICollection<Type>.IsReadOnly
    {
        get
        {
            return false;
        }
    }

    public void Clear()
    {
        _collection.Clear();
    }

    public void CopyTo(Type[] array, int arrayIndex)
    {
        _collection.CopyTo(array, arrayIndex);
    }

    public IEnumerator<Type> GetEnumerator()
    {
        return _collection.GetEnumerator();
    }

    #region ICollection<Type> Members

    void ICollection<Type>.Add(Type item)
    {
        VerifyType(item);
        _collection.Add(item);
    }

    bool ICollection<Type>.Contains(Type item)
    {
        VerifyType(item);
        return _collection.Contains(item);
    }

    bool ICollection<Type>.Remove(Type item)
    {
        VerifyType(item);
        return _collection.Remove(item);
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    private void VerifyType(Type item)
    {
        if (!typeof(TBaseType).IsAssignableFrom(item))
            throw new ArgumentException("The type is incompatible.", "item");
    }
}
0 голосов
/ 30 мая 2012

Можно получить набор вещей, которые соблюдают несколько общих ограничений, без использования Reflection, но это довольно странно. Каждый элемент, добавленный в коллекцию, должен быть обернут в объект класса. Если предполагается, что коллекция содержит вещи, ограниченные I1 и I2, каждый элемент будет заключен в экземпляр универсального класса с типами T, I1 и I2 (с ограничением T:I1,I2 ), который реализует интерфейс с универсальными типами I1 и I2. Сама коллекция будет содержать ссылки этого типа интерфейса.

Если кому-то интересно, я мог бы опубликовать более подробную информацию.

0 голосов
/ 20 января 2010

Для этого вам нужно создать класс Type (Of TBase), а затем составить их список. Тогда вы можете попытаться гарантировать, что Type (Of TBase) статически корректен.

Но в большинстве случаев, когда вам нужно создать Type (Of TBase) из CLR Type, это можно гарантировать только динамически.

0 голосов
/ 20 января 2010

Я не думаю, что это может быть проверено статически во время компиляции. Но вы можете переопределить Add, AddRange и this [] для проверки добавленных элементов во время выполнения.

0 голосов
/ 20 января 2010

Нет, это не может быть.Тип в общем должен быть разрешен во время компиляции.

...