abstract class Class1
{
public abstract IEnumerator<Class1> GetItems();
}
class Class2 : Class1
{
public override IEnumerator<Class2> GetItems()
{
throw new NotImplementedException();
}
}
А вот такой — по прежнему нет:
class Class3 : IEnumerable<Class3>
{
public IEnumerator<Class3> GetEnumerator()
{
throw new NotImplementedException();
}
}
C>По твоей логике, в Class2 базовый класс тоже "имплементирован не полностью".
На 4.7.2 ошибка, что "target runtime does not support covariant type in overrides".
Как поддержка "covariant type in overrides" по твоему связана с необходимостью определить Enumerable.GetEnumerator?
Здравствуйте, m2user, Вы писали:
M>На 4.7.2 ошибка, что "target runtime does not support covariant type in overrides". M>Как поддержка "covariant type in overrides" по твоему связана с необходимостью определить Enumerable.GetEnumerator?
Ну так у тебя версия древняя. Зачем ты стал на ней проверять?
Начиная с какой-то версии, ковариантность в классах уже работает.
C>По твоей логике, в Class2 базовый класс тоже "имплементирован не полностью".
Полностью, иначе бы компилятор ругнулся. Ни Class1 ни Class2 не наследуют IEnumerable, поэтому к ним у компилятора другое отношение. Учитывая время вопроса — овертаймишь небось?
Здравствуйте, hi_octane, Вы писали:
_>Полностью, иначе бы компилятор ругнулся. Ни Class1 ни Class2 не наследуют IEnumerable, поэтому к ним у компилятора другое отношение.
Раньше ругался, нужно было точное совпадение сигнатуры. Начиная с какой-то версии, достаточно совместимой сигнатуры. Возвращаемый тип можно изменить, если он более derived.
Но это только в классах. В интерфейсах — нет.
Вопрос — почему?
_>Учитывая время вопроса — овертаймишь небось?
У меня — середина дня. Про разные зоны времени никогда не слышал?
Здравствуйте, m2user, Вы писали:
M>Видимо ты имеешь в виду, что IEnumerator<Class3> GetEnumerator() и IEnumerator IEnumerable.GetEnumerator() можно было бы имплементировать одним методом.
C>Но это только в классах. В интерфейсах — нет. C>Вопрос — почему?
Может про интерфейсы команда шарпа думала что методы интерфейса вместе связаны, и хотела сохранить некую консистентность между ними И потому сделали ковариантность возвращаемых значений пачке методов через out T. Наверное их идея была в том, что класс реализует внутри себя максимально специфичную версию, а пользователь уж выбирает подходящего предка.
Кстати, если иерархия будет Class2 : (Class1 : IA<object>), всё равно пример правильно отработает. Но в "сложной иерархии" с out и без out поведение будет разное.
using System;
using System.Collections;
using System.Collections.Generic;
interface IA<out T>
{
T GetT();
}
class Class2 : IA<string>
{
public string GetT() => "str";
}
public class HelloWorld
{
public static void Main(string[] args)
{
Class2 c = new();
IA<object> ia = c; //кому нужен object - тот использует object
Console.WriteLine(ia.GetT());
}
}
C>У меня — середина дня. Про разные зоны времени никогда не слышал?
А, ну значит всё наоборот, эт я с трудом догоняю...
Здравствуйте, hi_octane, Вы писали:
_>Может про интерфейсы команда шарпа думала что методы интерфейса вместе связаны, и хотела сохранить некую консистентность между ними
Да не. Судя по спеке, которую нашел m2user, такую фичу они рассматривали, но потом просто забыли /забили. Бардак-с.