3

Я пишу общий абстрактный класс А с параметром Т типа, что я намерен вывести с класса В.C# Непатентованные и Generic ограничения

А имеет элемент данных, Mx, экземпляр класса С, с общая функция. Эта универсальная функция GetAllOfType() имеет один параметр типа T. Этот тип параметра ограничен третьим классом, D. GetAllOfType() ищет через контейнер экземпляров D, который включает в себя экземпляры D-производных классов и возвращает подмножество, которое имеет тип T (следовательно, ограничение на D).

сам

Класс D не имеет конкретного члена данных, внутр мой, но некоторые производные классы D сделать, например, E и F.

public class D 
{ 
} 

public class E : D 
{ 
    public int mY; 
} 

public class F : D 
{ 
    public int mY; 
} 

public class C 
{ 
    public T[] GetAllOfType<T>() where T : D 
    { ... } 
} 

public class A<T> 
{ 
    private C mX; 
    ... 
} 

public class B : A<E> 
{ 
    ... 
} 

Так вот где начинается моя проблема:

Тип параметра, который класс B использует для наследования и реализации класса A, является производным классом D. Я пытаюсь написать функцию Foo в классе A, которая перечисляет через GetAllOfType() и получает доступ к члену mY типа E, F или любому другому член, который имеет mY.

public class A<T> 
{ 
    private C mX; 

    protected Foo() 
    { 
     foreach (var c in mX.GetAllOfType<T>()) 
     { 
      c.mY = 0; 
     } 
    } 
} 

public class B : A<E> 
{ 
    public Bar() 
    { 
     Foo(); 
    } 
} 

Проблема, однако, заключается в том, что GetAllOfType() ограничен, и я получаю сообщение об ошибке для не стесняя класса А, а также.

Я попытался сдерживая как таковые:

public class A<T> where T : D 

Но я получаю ошибку во время компиляции вдоль линий:

Типа T' does not contain a definition for моего»и нет методы расширения mY' of type T (вы не можете найти ссылку на использование или ссылку на сборку?)

Я также пытался ограничить несколько привели к расколу классы:

public class A<T> where T : E, F 

Но я получаю сообщение об ошибке, а также по линии:

типа класса ограничения «F» должны быть перечислены до каких-либо других ограничений. Рассмотрим перемещение ограничение типа в начале списка ограничений

Я попытался их переключения:

public class A<T> where T : F, E 

Аналогично, результат тот же ошибка, но с F переключился на E.

Является ли то, что я пытаюсь сделать возможным? Что я делаю не так?

Опять же, я не могу изменить что-либо о классах C, D, E и F.

+0

Вы пробовали 'foreach (T c в mX.GetAllOfType ())' - В этом случае вам нужно переместить элемент 'mY' в ваш базовый класс' D'. В случае 'public class A где T: E, F' код ожидает, что' T' реализует 'E' и' F', если я не ошибаюсь. –

+0

Любой, почему бы не добавить 'int mY' в' class D', поскольку все производные классы имеют его? – ja72

ответ

2

При добавлении ограничение на общий параметр A,

public class A<T> where T : D 

причина вы получите второй ошибка, Type T' does not contain a definition for mY' and no extension method mY' of typeT' could be found (are you missing a using directive or an assembly reference?), неудивительно, потому что D не имеет mY, только производные классы E и F.Причина

public class A<T> where T : E, F 

не работает, потому что вы можете указать только один тип ограничения базового класса (C# не имеет множественное наследование). Любые дополнительные ограничения должны быть интерфейсами или такими вещами, как class или new()

Если вы действительно ничего не можете изменить об этих классах, то то, что вы пытаетесь выполнить, может быть неоправданно трудным, насколько я могу судить. Я могу придумать некоторые уродливые способы (отражение или много кастингов), но это не может быть правильным путем. Может быть, есть что-то умное, которого я пропускаю. Было бы здорово, если бы вы могли ввести интерфейс (или промежуточный класс) с свойством mY и наследовать от E и F. Тогда вы могли бы сдержать T до этого, а не D, и все будет честно. В противном случае я не вижу никакого способа узнать, с какими D вы имеете дело, кроме как во время выполнения.

+1

Отражение - это «правильный» способ определения свойств, которые не определены с помощью какой-либо формы наследования. Это может быть не чисто, но это делает работу. – Guvante

+0

@ Гуванте да, и, возможно, это несправедливо называть его уродливым. Я надеялся каким-то образом решить проблему, не прибегая к проверке времени выполнения. – Bort

+0

Без проверки времени выполнения означает, в основном, новый (реальный, владеет свойством mY) интерфейс. Если вам нужно взаимодействовать со всеми производными от D, которые также обладают свойством mY, вам нужно ввести общий предок E и F, которые выставляют mY. Это может быть абстрактный класс (LocalD, для аргумента) или интерфейс (IHavemY). –