Если вы посмотрите на исходный код для итератора ArrayList
(частный вложенный класс Itr
), вы увидите недостаток в коде.
Код должен быть с ошибкой, быстрый, который делается внутри итератора внутри, вызывая checkForComodification()
, однако hasNext()
не делает этот вызов, вероятно, по соображениям производительности.
Вместо hasNext()
:
public boolean hasNext() {
return cursor != size;
}
Это означает, что когда вы находитесь в элементе second last в списке, а затем удалите элемент (любой элемент), размер уменьшается, а hasNext()
думает, что вы 're на последнем элементе (которого вы не были) и возвращает false
, пропуская итерацию последнего элемента без ошибок.
OOPS !!!!
Потому что вы не можете. Дженерики - это не шаблоны. Вы не должны думать о них, как шаблоны C ++, и ожидать такого же поведения.
Спецификация C # явно запрещает использование параметров типа в качестве базового класса:
C # 3.0 Спецификация языка: параметры типа (§4.5)
Параметр типа не может использоваться напрямую для объявления базового класса (§10.2.4) или интерфейса (§13.1.3).
blockquote>Обновление:
Я понимаю, что вы хотите сделать и его использование. Это традиционный пример использования шаблонов C ++. В частности, если это было возможно сделать с использованием генераторов C #, такие вещи, как
Moq
library , могли бы быть полезны. Проблема в том, что C ++-шаблоны - это время компиляции «find and replace», в то время как C # generics - это время выполнения.Чтобы продемонстрировать этот факт, для этого класса:
class Test<T> where T : class { // whatever contents it might have... }
только один ИЛ будет выпущен во время компиляции и во время выполнения, компилятор JIT будет генерировать единый собственный код для всех типов типа ссылочного типа. Это совсем не похоже на C ++-шаблоны, где собственный код будет испускаться для каждого
T
отдельно (он подвержен оптимизации, но концептуально, они являются полностью отдельными фрагментами кода).
Вы не можете наследовать от параметра generic type, потому что этот тип неизвестен во время компиляции, поэтому компилятор не может понять, что такое суперкласс. Я понимаю, что на первый взгляд тот факт, что компилятор может определить, что & lt; T & gt; похоже, предполагает, что он должен иметь возможность выяснить, что такое T, но две вещи разные.
Кроме того, у вас есть логическая проблема в баре. Вы не можете вызвать base.Bar, потому что это абстрактный тип. Чтобы исправить это, вам нужно будет изменить свою реализацию в Foo на
public virtual void Bar() {}
Поскольку Foo является абстрактным типом.
Если вы внедрили Foo в класс, то использовали его в шаблоне, тогда вы могли бы это сделать.
Вы также можете использовать интерфейс для сделайте то, что вы пытаетесь сделать, я верю.
Edit:
Во второй раз, глядя на ваш код, это бессмысленно. Вам нужно будет создать базовый класс типа GENERIC, а затем извлечь из этого, чтобы достичь того, что вы пытаетесь сделать. Это также придало бы еще больший смысл ...
abstract class Foo<T>
{
public virtual void Bar();
}