Преобразование в IEnumerable возможно, но для ICollection невозможно [дублировать]

Я предпочитаю использовать селектор, и я применяю его в документе.

Это привязывается к документу и будет применяться к элементам, которые будут отображаться после загрузки страницы.

Например:

$(document).on("click", $(selector), function() {
    // Your code here
});
43
задан Alexei Levenkov 13 April 2017 в 19:55
поделиться

4 ответа

Обновление

: начиная с .NET 4.5 есть IReadOnlyList<out T> и IReadOnlyCollection<out T> , которые являются ковариантными; Последний в основном IEnumerable<out T> плюс Count; первый добавляет T this[int index] {get;}. Следует также отметить, что IEnumerable<out T> ковариантно от .NET 4.0 и далее.

И List<T>, и ReadOnlyCollection<T> (через List<T>.AsReadOnly() ) реализуют обе эти функции.


Он может быть только ковариантным, если он имеет только индекс get, т. е.

public T this[int index] { get; }

Но все основные коллекции имеют {get;set;}, что делает это неудобным. Я не знаю о том, что этого достаточно, но вы можете обернуть , т. Е. Написать метод расширения:

var covariant = list.AsCovariant();

, который является оберткой вокруг IList<T> который предоставляет только IEnumerable<T> и get индексатор ...? должно быть всего несколько минут работы ...

public static class Covariance
{
    public static IIndexedEnumerable<T> AsCovariant<T>(this IList<T> tail)
    {
        return new CovariantList<T>(tail);
    }
    private class CovariantList<T> : IIndexedEnumerable<T>
    {
        private readonly IList<T> tail;
        public CovariantList(IList<T> tail)
        {
            this.tail = tail;
        }
        public T this[int index] { get { return tail[index]; } }
        public IEnumerator<T> GetEnumerator() { return tail.GetEnumerator();}
        IEnumerator IEnumerable.GetEnumerator() { return tail.GetEnumerator(); }
        public int Count { get { return tail.Count; } }
    }
}
public interface IIndexedEnumerable<out T> : IEnumerable<T>
{
    T this[int index] { get; }
    int Count { get; }
}
47
ответ дан Marc Gravell 19 August 2018 в 00:12
поделиться
  • 1
    @ user731000 - см. обновление – Marc Gravell♦ 29 April 2011 в 13:48
  • 2
    Благодарю. Это лучший путь вперед. – Brian M 29 April 2011 в 17:22
  • 3
    Иногда мне хотелось, чтобы Microsoft смогла наследовать IList от суб-интерфейсов IReadableByIndex (который вы называете IIndexedEnumerable), IWritableByIndex и iAppendable, чтобы обеспечить полезную ковариацию и контравариантность. К сожалению, до сих пор нет возможности для свойства «только для чтения» или «запись», которое должно быть реализовано с помощью свойства «чтение-запись». Если это можно было бы сделать, все члены ковариантных / контравариантных суб-интерфейсов, естественно, были бы реализованы с помощью любой действительной реализации IList, поэтому суб-интерфейсы могли бы быть добавлены без нарушения существующего кода. – supercat 14 June 2011 в 21:52
  • 4
    – supercat 14 June 2011 в 22:02
  • 5
    – Lucas Trzesniewski 20 November 2014 в 11:23

Технически, есть коллекция массивов. Это своего рода нарушение в своей дисперсии, но оно делает то, что вы просите.

IList<Animal> animals;
List<Dog> dogs = new List<Dog>();
animals = dogs.ToArray();

Вы, конечно, будете взрываться довольно эффектно во время выполнения, если вы попытаетесь поместить Tiger в массив где угодно .

3
ответ дан Anthony Pegram 19 August 2018 в 00:12
поделиться

Вот этот класс, который я написал для решения этой проблемы:

public class CovariantIListAdapter<TBase, TDerived> : IList<TBase>
    where TDerived : TBase
{
    private IList<TDerived> source;

    public CovariantIListAdapter(IList<TDerived> source)
    {
        this.source = source;
    }

    public IEnumerator<TBase> GetEnumerator()
    {
        foreach (var item in source)
            yield return item;
    }

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

    public void Add(TBase item)
    {
        source.Add((TDerived) item);
    }

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

    public bool Contains(TBase item)
    {
        return source.Contains((TDerived) item);
    }

    public void CopyTo(TBase[] array, int arrayIndex)
    {
        foreach (var item in source)
            array[arrayIndex++] = item;
    }

    public bool Remove(TBase item)
    {
        return source.Remove((TDerived) item);
    }

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

    public bool IsReadOnly
    {
        get { return source.IsReadOnly; }
    }

    public int IndexOf(TBase item)
    {
        return source.IndexOf((TDerived) item);
    }

    public void Insert(int index, TBase item)
    {
        source.Insert(index, (TDerived) item);
    }

    public void RemoveAt(int index)
    {
        source.RemoveAt(index);
    }

    public TBase this[int index]
    {
        get { return source[index]; }
        set { source[index] = (TDerived) value; }
    }
}

Теперь вы можете написать такой код:

List<Dog> dogs = new List<Dog>();
dogs.Add(new Dog { Name = "Spot", MaximumBarkDecibals = 110 });

IEnumerable<Animal> animals = dogs;
IList<Animal> animalList = new CovariantIListAdapter<Animal, Dog>(dogs);

animalList.Add(new Dog { Name = "Fluffy", MaximumBarkDecibals = 120 });

Изменения видны в обоих списках, потому что там действительно все еще только 1 список. Класс адаптера просто передает вызовы, при необходимости накладывая элементы для достижения желаемого интерфейса IList<TBase>.

Очевидно, что если вы добавите что-либо, кроме Dogs, в animalList, оно выдает исключение, но это удовлетворил мои потребности.

6
ответ дан G-Mac 19 August 2018 в 00:12
поделиться
  • 1
    для этого вам не нужно создавать новый адаптер. Просто создайте новый список. например: новый список & lt; Animal & gt; (собаки), и все будет работать нормально. Вы можете, хотя это не решит проблему противоречия. – Shoaib Shakeel 17 July 2015 в 18:47
  • 2
    Это полиморфизм, даже вы добавили объект, отличный от Animal. эта ссылка msdn.microsoft.com/en-us/library/ee207183.aspx описывает о ковариации и контравариантности – natnael88 29 January 2016 в 16:50
  • 3

В .NET Framework 4.5 существует интерфейс IReadOnlyList, который является ковариантным. Это по сути то же, что и интерфейс IIndexedEnumerable в ответе Марка Гравелла.

IReadOnlyList реализуется следующим образом:

  /// <summary>
  /// Represents a read-only collection of elements that can be accessed by index.
  /// </summary>
  /// <typeparam name="T">The type of elements in the read-only list. This type parameter is covariant. That is, you can use either the type you specified or any type that is more derived. For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</typeparam>
    public interface IReadOnlyList<out T> : IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
      {
        /// <summary>
        /// Gets the element at the specified index in the read-only list.
        /// </summary>
        /// 
        /// <returns>
        /// The element at the specified index in the read-only list.
        /// </returns>
        /// <param name="index">The zero-based index of the element to get. </param>
        T this[int index] { get; }
      }
3
ответ дан Tongfei Chen 19 August 2018 в 00:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: