Список неизвестных типов общего типа или вызов общего подкласса [дубликат]

Официальный учебник может вам пригодиться.

            │ Class │ Package │ Subclass │ Subclass │ World
            │       │         │(same pkg)│(diff pkg)│ 
────────────┼───────┼─────────┼──────────┼──────────┼────────
public      │   +   │    +    │    +     │     +    │   +     
────────────┼───────┼─────────┼──────────┼──────────┼────────
protected   │   +   │    +    │    +     │     +    │         
────────────┼───────┼─────────┼──────────┼──────────┼────────
no modifier │   +   │    +    │    +     │          │    
────────────┼───────┼─────────┼──────────┼──────────┼────────
private     │   +   │         │          │          │    

+ : accessible
blank : not accessible

5
задан Cuong Le 9 October 2012 в 05:50
поделиться

4 ответа

это невозможно, насколько мне известно.

строка:

List<ValuePair> list = new List<ValuePair>();

, которую вы написали в своем примере, не предоставляет конкретный тип для T, и это проблема , как только вы его передадите, вы можете добавить объект только этого типа.

1
ответ дан Davide Piras 25 August 2018 в 22:28
поделиться

В общем случае вам придется либо использовать List<object>, либо создать не общий базовый класс, например

public abstract class ValuePair
{
    public string Name { get; set;}
    public abstract object RawValue { get; }
}

public class ValuePair<T> : ValuePair
{
    public T Value { get; set; }              
    public object RawValue { get { return Value; } }
}

. Тогда вы можете иметь List<ValuePair>.

Теперь существует одно исключение: ковариантные / контравариантные типы в C # 4. Например, вы можете написать:

var streamSequenceList = new List<IEnumerable<Stream>>();

IEnumerable<MemoryStream> memoryStreams = null; // For simplicity
IEnumerable<NetworkStream> networkStreams = null; // For simplicity
IEnumerable<Stream> streams = null; // For simplicity

streamSequenceList.Add(memoryStreams);
streamSequenceList.Add(networkStreams);
streamSequenceList.Add(streams);

Это неприменимо в ваш случай, потому что:

  • Вы используете общий класс, а не интерфейс
  • . Вы не можете изменить его на общий ковариационный интерфейс потому что у вас T происходит «in» и «out» API
  • . Вы используете типы значений в качестве аргументов типа, и они не работают с (поэтому IEnumerable<int> не является IEnumerable<object>)
11
ответ дан Jon Skeet 25 August 2018 в 22:28
поделиться

Нет, это невозможно. Вы можете создать в вашем случае базовый класс ValuePair, из которого выводится ValuePair<T>. Зависит от ваших целей.

1
ответ дан Lorenzo Dematté 25 August 2018 в 22:28
поделиться

Нет, если у вас нет универсального базового типа ValuePair с ValuePair<T> : ValuePair (он также будет работать для интерфейса) или используйте List<object>. На самом деле это работает разумно:

public abstract class ValuePair
{
    public string Name { get; set; }
    public object Value
    {
        get { return GetValue(); }
        set { SetValue(value); }
    }
    protected abstract object GetValue();
    protected abstract void SetValue(object value);
}
public class ValuePair<T> : ValuePair
{
    protected override object GetValue() { return Value; }
    protected override void SetValue(object value) { Value = (T)value; }
    public new T Value { get; set; }
}
4
ответ дан Marc Gravell 25 August 2018 в 22:28
поделиться
Другие вопросы по тегам:

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