ковариантность в C#
От: Klatu  
Дата: 08.11.10 15:13
Оценка: :)
В C# 4 вроде появилась ковариантность в каком-то виде... значит ли это, что наконец можно передавать string[] в метод, который требует object[] ?
Re: ковариантность в C#
От: _FRED_ Черногория
Дата: 08.11.10 15:16
Оценка: +4
Здравствуйте, Klatu, Вы писали:

K>В C# 4 вроде появилась ковариантность в каком-то виде... значит ли это, что наконец можно передавать string[] в метод, который требует object[] ?


Это можно было ещё в первом фреймворке.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: ковариантность в C#
От: _FRED_ Черногория
Дата: 08.11.10 15:18
Оценка:
Здравствуйте, _FRED_, Вы писали:

K>>В C# 4 вроде появилась ковариантность в каком-то виде... значит ли это, что наконец можно передавать string[] в метод, который требует object[] ?


_FR>Это можно было ещё в первом фреймворке.


Вернее, в первом шарпе.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: ковариантность в C#
От: Klatu  
Дата: 08.11.10 15:34
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Это можно было ещё в первом фреймворке.


Ах действительно, для массивов можно, это для интерфейсов коллекций нельзя.
Впрочем, для массивов тоже не всегда льзя
С этим что-нибудь изменилось?
Re[3]: ковариантность в C#
От: nikov США http://www.linkedin.com/in/nikov
Дата: 08.11.10 15:38
Оценка: 4 (2)
Здравствуйте, Klatu, Вы писали:

K>Ах действительно, для массивов можно, это для интерфейсов коллекций нельзя.

K>Впрочем, для массивов тоже не всегда льзя
K>С этим что-нибудь изменилось?

Для интерфейсов изменилось то, что теперь можно передавать IEnumerable<string> вместо IEnumerable<object>.
Для массивов теперь можно передавать IEnumerable<string>[] вместо IEnumerable<object>[]. Передавать int[] вместо object[] по-прежнему нельзя.
Re[4]: ковариантность в C#
От: Klatu  
Дата: 08.11.10 15:40
Оценка:
Здравствуйте, nikov, Вы писали:

N>Для интерфейсов изменилось то, что теперь можно передавать IEnumerable<string> вместо IEnumerable<object>.

N>Для массивов теперь можно передавать IEnumerable<string>[] вместо IEnumerable<object>[]. Передавать int[] вместо object[] по-прежнему нельзя.

Эх, как всё печально...
Re[5]: ковариантность в C#
От: nikov США http://www.linkedin.com/in/nikov
Дата: 08.11.10 15:58
Оценка:
Здравствуйте, Klatu, Вы писали:

K>Эх, как всё печально...


А какое положение дел тебя бы устроило?
Re[3]: ковариантность в C#
От: _FRED_ Черногория
Дата: 08.11.10 15:59
Оценка: +1
Здравствуйте, Klatu, Вы писали:

_FR>>Это можно было ещё в первом фреймворке.


K>Ах действительно, для массивов можно, это для интерфейсов коллекций нельзя.

K>Впрочем, для массивов тоже не всегда льзя
K>С этим что-нибудь изменилось?

Эх, такой ответ накатал, а сообщение удалено Поэтому теперь коротко — продвижек относительно массивов структур ждать и не следует. Ибо

Unfortunately, this particular kind of covariance is broken. It was added to the CLR because Java requires it and the CLR designers wanted to be able to support Java-like languages. We then up and added it to C# because it was in the CLR. This decision was quite controversial at the time and I am not very happy about it, but there’s nothing we can do about it now.

Why is this broken? Because it should always be legal to put a Turtle into an array of Animals. With array covariance in the language and runtime you cannot guarantee that an array of Animals can accept a Turtle because the backing store might actually be an array of Giraffes.

This means that we have turned a bug which could be caught by the compiler into one that can only be caught at runtime. This also means that every time you put an object into an array we have to do a run-time check to ensure that the type works out and throw an exception if it doesn’t. That’s potentially expensive if you’re putting a zillion of these things into the array.

Yuck.


здесь
Help will always be given at Hogwarts to those who ask for it.
Re[4]: ковариантность в C#
От: Klatu  
Дата: 08.11.10 16:18
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Эх, такой ответ накатал, а сообщение удалено Поэтому теперь коротко — продвижек относительно массивов структур ждать и не следует. Ибо


Ну черт с ними, это не так уж критично. Но с интерфейсами коллекций то надо хоть что-то сделать
Пусть бы сделали хотя бы рантайм проверку, как с массивами. Если их так сильно заботит производительность — можно добавить метод AddMany(T)
Re[5]: ковариантность в C#
От: _FRED_ Черногория
Дата: 08.11.10 16:23
Оценка: +1
Здравствуйте, Klatu, Вы писали:

_FR>>Эх, такой ответ накатал, а сообщение удалено Поэтому теперь коротко — продвижек относительно массивов структур ждать и не следует. Ибо


K>Ну черт с ними, это не так уж критично. Но с интерфейсами коллекций то надо хоть что-то сделать

K>Пусть бы сделали хотя бы рантайм проверку, как с массивами. Если их так сильно заботит производительность — можно добавить метод AddMany(T)

Чт о-то не понятно, что нужно делать с интерфейсами коллекций, при чём тут производительность и как с этим связаны AddMany(T) и ковариантность?

AddMany(T) и сейчас уже можно написать для любой коллекции с помощью extension-методов.
Help will always be given at Hogwarts to those who ask for it.
Re[6]: ковариантность в C#
От: Klatu  
Дата: 08.11.10 16:27
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Чт о-то не понятно, что нужно делать с интерфейсами коллекций, при чём тут производительность и как с этим связаны AddMany(T) и ковариантность?


Сделать надо, чтобы метод IList<object> принимал ссылку на IList<SomeConcreteType>
А производительность — это та самая проблема и ее решение рантайм-чеками, про которую ты цитировал чуть выше
Re[7]: ковариантность в C#
От: _FRED_ Черногория
Дата: 08.11.10 17:06
Оценка:
Здравствуйте, Klatu, Вы писали:

_FR>>Чт о-то не понятно, что нужно делать с интерфейсами коллекций, при чём тут производительность и как с этим связаны AddMany(T) и ковариантность?


K>Сделать надо, чтобы метод IList<object> принимал…


IList<object> — это не метод. Речь о каком-то конкретном методе этого интерфейса?

K>… принимал ссылку на IList<SomeConcreteType>


Для чего

Чем не подойдёт такое:

public static void AddMany<T1, T2>(this ICollection<T1> source, IEnumerable<T2> items) where T1: class, T2: class, T1 {
  foreach(var item in items) {
    source.Add(item);
  }//for
}



K>А производительность — это та самая проблема и ее решение рантайм-чеками, про которую ты цитировал чуть выше


То, что я цитировал к IList имеет мало отношения. Там чётко говорилось о массивах. И с IList нельзя делать того же, что и с массивом не потгому что так дороги рантайм-проверки, а потому-то компайл-тайм проверка гораздо лучше и именно она имеется в IEnumerable.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: ковариантность в C#
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.11.10 17:15
Оценка: +1
Здравствуйте, _FRED_, Вы писали:

K>>В C# 4 вроде появилась ковариантность в каком-то виде... значит ли это, что наконец можно передавать string[] в метод, который требует object[] ?


_FR>Это можно было ещё в первом фреймворке.


И за это надо был с работы выгнать тех ламеров кто допустил ковариантность на изменяемых структурах данных.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[8]: ковариантность в C#
От: Klatu  
Дата: 08.11.10 17:20
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>IList<object> — это не метод. Речь о каком-то конкретном методе этого интерфейса?


Речь идет о методе, который принимает этот интерфейс как один из параметров.
Re[3]: ковариантность в C#
От: Klatu  
Дата: 08.11.10 17:22
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>И за это надо был с работы выгнать тех ламеров кто допустил ковариантность на изменяемых структурах данных.


read-only коллекции не вложили в язык с библиотекой, вот один косяк за другой и тянет
Re[4]: ковариантность в C#
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.11.10 17:22
Оценка: +1
Здравствуйте, _FRED_, Вы писали:

_FR>

_FR>Unfortunately, this particular kind of covariance is broken. It was added to the CLR because Java requires it and the CLR designers wanted to be able to support Java-like languages. We then up and added it to C# because it was in the CLR. This decision was quite controversial at the time and I am not very happy about it, but there’s nothing we can do about it now.

_FR>Why is this broken? Because it should always be legal to put a Turtle into an array of Animals. With array covariance in the language and runtime you cannot guarantee that an array of Animals can accept a Turtle because the backing store might actually be an array of Giraffes.

_FR>This means that we have turned a bug which could be caught by the compiler into one that can only be caught at runtime. This also means that every time you put an object into an array we have to do a run-time check to ensure that the type works out and throw an exception if it doesn’t. That’s potentially expensive if you’re putting a zillion of these things into the array.

_FR>Yuck.


Ага. Только врут, как всегда, немного. Конечно же сделано это не из-за того, что "Java requires it and the CLR designers wanted to be able to support Java-like languages", а потому, что первый фрэймворк был тупым клоном явы. Не задумываясь содрали и системный баг.

Самое смешное, что я практически не видел использования ковариантности для массивов на практике. Но оверхэд от этого мы имеем при любом присвоении ссылки в любой массив!
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: ковариантность в C#
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.11.10 17:37
Оценка:
Здравствуйте, Klatu, Вы писали:

VD>>И за это надо был с работы выгнать тех ламеров кто допустил ковариантность на изменяемых структурах данных.


K>read-only коллекции не вложили в язык с библиотекой, вот один косяк за другой и тянет


А причем тут "read-only коллекции"? С каких пор массивы стали "read-only"?

Да и не использует никто ковариантность массивов. Вот ты даже не знал, что она есть.

Еще раз повторяю — это просто фича содранная с Явы. Причем содранная по глупости. Сейчас мы платим за нее понижением производительности и возможностью сделать ошибки которые до выполнения не будут обнаружены.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: ковариантность в C#
От: Klatu  
Дата: 08.11.10 17:44
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>А причем тут "read-only коллекции"? С каких пор массивы стали "read-only"?


Ни с каких
Нет никаких коллекций read-only в .NET, вообще нету. Только пакостная эмуляция на рантаймовых проверках.

VD>Да и не использует никто ковариантность массивов. Вот ты даже не знал, что она есть.


Знал, просто забыл. Я массивы вообще использую сравнительно редко.
Проблема в том, что хочется написать генерический метод просто и незатейливо — Foo(IList<T> vals)
А вот хрен тебе
Re[4]: ковариантность в C#
От: _FRED_ Черногория
Дата: 08.11.10 17:47
Оценка:
Здравствуйте, Klatu, Вы писали:

VD>>И за это надо был с работы выгнать тех ламеров кто допустил ковариантность на изменяемых структурах данных.


K>read-only коллекции не вложили в язык с библиотекой, вот один косяк за другой и тянет


Всё равно не понятно — написали бы что ли пример кода
Help will always be given at Hogwarts to those who ask for it.
Re[5]: ковариантность в C#
От: nikov США http://www.linkedin.com/in/nikov
Дата: 08.11.10 17:50
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Еще раз повторяю — это просто фича содранная с Явы. Причем содранная по глупости.


Не совсем так. Дизайнеры CLR и C# прекрасно понимали все издержки этого решения в Java. Но была бизнес-цель: облегчить миграцию кода, написанного на Java, на C#. И ради достижения этой цели пришлось, скрепя сердце, поддержать и эту фичу.
Re[6]: ковариантность в C#
От: _nn_ www.nemerleweb.com
Дата: 08.11.10 17:57
Оценка:
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, VladD2, Вы писали:


VD>>Еще раз повторяю — это просто фича содранная с Явы. Причем содранная по глупости.


N>Не совсем так. Дизайнеры CLR и C# прекрасно понимали все издержки этого решения в Java. Но была бизнес-цель: облегчить миграцию кода, написанного на Java, на C#. И ради достижения этой цели пришлось, скрепя сердце, поддержать и эту фичу.


Кому надо с Java перешли, поэтому к 4-му фреймворку могли бы ее отключить
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[7]: ковариантность в C#
От: nikov США http://www.linkedin.com/in/nikov
Дата: 08.11.10 17:59
Оценка: +3
Здравствуйте, _nn_, Вы писали:

__>Кому надо с Java перешли, поэтому к 4-му фреймворку могли бы ее отключить


Я уверен, что до сих пор в продакшене есть C# код (возможно, мигрировавший с Java), который использует эту фичу. Его нельзя вот просто так сломать.
Re[8]: ковариантность в C#
От: _nn_ www.nemerleweb.com
Дата: 08.11.10 18:03
Оценка: +2
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, _nn_, Вы писали:


__>>Кому надо с Java перешли, поэтому к 4-му фреймворку могли бы ее отключить


N>Я уверен, что до сих пор в продакшене есть C# код (возможно, мигрировавший с Java), который использует эту фичу. Его нельзя вот просто так сломать.


Можно было начать с предупреждения, а к 5-му убрать.
Хотя предупреждение должно было быть еще во 2-м..
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[6]: ковариантность в C#
От: Jack128  
Дата: 08.11.10 19:22
Оценка:
Здравствуйте, Klatu, Вы писали:

K>Проблема в том, что хочется написать генерический метод просто и незатейливо — Foo(IList<T> vals)

чем тебя Foo(IEnumerable<T> vals) не устраивает?
Re[7]: ковариантность в C#
От: hi_octane Беларусь  
Дата: 08.11.10 20:07
Оценка: 1 (1) +2 :)
K>>Проблема в том, что хочется написать генерический метод просто и незатейливо — Foo(IList<T> vals)
J>чем тебя Foo(IEnumerable<T> vals) не устраивает?

Меня тем что Count нету. Без серьёзного мозгового штурма, чисто навскидку стоило бы как-то наследовать вроде IDisposable->IEnumerable(MoveNext,Current,Reset)->ICollection(Count)->IIndexedCollection(IndexOf,this[]{get;})->IArray(this[]{set;}). И отдельно иерархия модифицирующих интерфейсов вроде ICollection->IWritableCollection(Add,Remove,Clear); IArray,IWritableCollection->IList(InsertAt,RemoveAt). И та же ковариантность массивов выражалась бы в том что (IIndexedCollection<object>)int[], работало бы, а (IArray<object>)int[] нет, т.к. object не положить в int[].

В общем не тот бардак что сейчас, когда int[] поддерживает IList и ICollection, но реализует из них едва-ли половину их методов и свойств. Да и как можно обработать все эти мутные проперти вроде IsReadOnly или IsFixedSize, если мне по логике программы в колекцию надо досыпать данных? Только проверить их в рантайме и свалиться с ассертом? Ерунда какая-то в общем.
Re[8]: ковариантность в C#
От: Jack128  
Дата: 08.11.10 20:10
Оценка:
Здравствуйте, hi_octane, Вы писали:

K>>>Проблема в том, что хочется написать генерический метод просто и незатейливо — Foo(IList<T> vals)

J>>чем тебя Foo(IEnumerable<T> vals) не устраивает?

_>Меня тем что Count нету.


есть линковский Count(). Он вроде на ICollection тестирует, так что для массивов быстро работает..
Re[9]: ковариантность в C#
От: hi_octane Беларусь  
Дата: 08.11.10 20:19
Оценка: +4 -1
J>есть линковский Count(). Он вроде на ICollection тестирует, так что для массивов быстро работает..
Вся идея статической типизации состоит в том чтобы получать максимум возможных проверок компилятором в компайл-тайме. Это как физика — если размерности не сошлись, значит формула ошибочна.

Теперь рассмотрим функцию которая объявлена в виде void Foo(IList<T> list). Из её определения ничерта непонятно, можно ли ей передать массив (который реализует IList), или она будет пытаться в него дописывать элементы и массив в итоге вылетит с исключением, а значит она принимает только List<T>. А вдруг она туда дописывает элементы не всегда а при особом сочетании звёзд на небе. Другого интерфейса который бы поддерживал индексированный нет. В итоге то что мог бы проверить компилятор в компайл-тайм, нужно проверять программисту и кидаться исключениями — косяк дизайна.
Re[6]: ковариантность в C#
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.11.10 21:58
Оценка:
Здравствуйте, Klatu, Вы писали:

K>Ни с каких

K>Нет никаких коллекций read-only в .NET, вообще нету. Только пакостная эмуляция на рантаймовых проверках.

Ну, это у кого как:
list.n
set.n
Map.n


VD>>Да и не использует никто ковариантность массивов. Вот ты даже не знал, что она есть.


K>Знал, просто забыл.


Что не меняет дела.

K>Я массивы вообще использую сравнительно редко.


А зря. Отличная штука чтобы вернуть список.

K>Проблема в том, что хочется написать генерический метод просто и незатейливо — Foo(IList<T> vals)

K>А вот хрен тебе

Дык в чем проблема то? В 4.0 этот интерфейс ковариантный.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: ковариантность в C#
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.11.10 22:01
Оценка:
Здравствуйте, nikov, Вы писали:

VD>>Еще раз повторяю — это просто фича содранная с Явы. Причем содранная по глупости.


N>Не совсем так. Дизайнеры CLR и C# прекрасно понимали все издержки этого решения в Java. Но была бизнес-цель: облегчить миграцию кода, написанного на Java, на C#. И ради достижения этой цели пришлось, скрепя сердце, поддержать и эту фичу.


Во уж не поверю. Сейчас они конечно именно так говорят. А тогда идея фик сбыла прикрутить к Яве события, т.е. сделать свою Яву но другую.

Никто в здравом уме не переводил имеющиеся проекты с Явы на Шарп. Вот ГУЙ для винды делали — это да. Но для этого ничего портировать не надо было.

ЗЫ

Интересно, а на Яве многие используют ковариантность массивов?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: ковариантность в C#
От: QrystaL Украина  
Дата: 08.11.10 22:04
Оценка: +2
K>>Проблема в том, что хочется написать генерический метод просто и незатейливо — Foo(IList<T> vals)
K>>А вот хрен тебе

VD>Дык в чем проблема то? В 4.0 этот интерфейс ковариантный.


Не совсем ))
public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
Re[8]: ковариантность в C#
От: VladD2 Российская Империя www.nemerle.org
Дата: 08.11.10 22:18
Оценка:
Здравствуйте, QrystaL, Вы писали:

QL>Не совсем ))

QL>
QL>public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
QL>


Вай! Супер! В МС живут действительно веселые люди. Хотя наверно дело в методах вроде:
    void Add(T item);
    void CopyTo(T[] array, int arrayIndex);
    bool Remove(T item);


За них, кстати, отдельно "спасибо" тому парню которого мы так горячо любим!
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: ковариантность в C#
От: _FRED_ Черногория
Дата: 09.11.10 06:12
Оценка: +1
Здравствуйте, hi_octane, Вы писали:

J>>есть линковский Count(). Он вроде на ICollection тестирует, так что для массивов быстро работает..

_>Вся идея статической типизации состоит в том чтобы получать максимум возможных проверок компилятором в компайл-тайме. Это как физика — если размерности не сошлись, значит формула ошибочна.

Это приведёт к чихарде с реализациями. Это слишком накладно поддерживать. Обсуждалось много лет назад ни один раз (например здесь
Автор: _FRED_
Дата: 09.05.07
). То же самое нужно и со стримами сделать (стрим на чтение только вперёд, с происвольным доступом и т.п.). В дотнете просто пошли другим путём, использовав Optional Features Pattern. Совершенно никаких проблем это не вызывает.

_>Теперь рассмотрим функцию которая объявлена в виде void Foo(IList<T> list). Из её определения ничерта непонятно, можно ли ей передать массив (который реализует IList), или она будет пытаться в него дописывать элементы и массив в итоге вылетит с исключением, …


Ну и что? Пускай вылетает

_>… а значит она принимает только List<T>.


А почему не Collection<>

Вообще, в описании метода должно быть сказано, что метод будет делать с переданным списком: читать/добавлять/изменять и каким критериям должен удовлетворять этот IList<>.

_>А вдруг она туда дописывает элементы не всегда а при особом сочетании звёзд на небе. Другого интерфейса который бы поддерживал индексированный нет. В итоге то что мог бы проверить компилятор в компайл-тайм, нужно проверять программисту и кидаться исключениями — косяк дизайна.


Лёгко вам выводы делать. Попробуйте для начала спроектировать библиотеку, которую придётся поддерживать лет двадцать или тридцать и состоящую из десятков тысяч типов. Матюгов по поводу того, что кто-то наплодил туеву хучу интерфейсов вы услышите сильно чаще.

Как минимум, правильные гайдлайны требуют по одной (а тут, возможно, понадобится и по две кое-где) реализации интерфейса в стандартной библиотеке. У меня получилось 6 интерфейсов. Какие интерфейсы предложили бы вы и какие реализации к ним?

Лучше примите, что есть — этим можно очень успешно и очень легко пользоваться.
Help will always be given at Hogwarts to those who ask for it.
Re[11]: ковариантность в C#
От: Jack128  
Дата: 09.11.10 06:47
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, hi_octane, Вы писали:


J>>>есть линковский Count(). Он вроде на ICollection тестирует, так что для массивов быстро работает..

_>>Вся идея статической типизации состоит в том чтобы получать максимум возможных проверок компилятором в компайл-тайме. Это как физика — если размерности не сошлись, значит формула ошибочна.

_FR>Это приведёт к чихарде с реализациями. Это слишком накладно поддерживать. Обсуждалось много лет назад ни один раз (например здесь
Автор: _FRED_
Дата: 09.05.07
). То же самое нужно и со стримами сделать (стрим на чтение только вперёд, с происвольным доступом и т.п.). В дотнете просто пошли другим путём, использовав Optional Features Pattern. Совершенно никаких проблем это не вызывает.


Любопытно, что за три года твое мнение по этому вопросу изменилось. Тогда ты сам предложил иерархию, аналогичную hi_octane Выглядит кста, вполне нормально, я б не отказался от такой реализации, вместо текущей.
Re[10]: ковариантность в C#
От: Jack128  
Дата: 09.11.10 06:48
Оценка:
Здравствуйте, hi_octane, Вы писали:

J>>есть линковский Count(). Он вроде на ICollection тестирует, так что для массивов быстро работает..

_>Вся идея статической типизации состоит в том чтобы получать максимум возможных проверок компилятором в компайл-тайме. Это как физика — если размерности не сошлись, значит формула ошибочна.

Не, я все понимаю. Я то просто практическое решение задачи топик стартера предложил.
Re[7]: ковариантность в C#
От: _FRED_ Черногория
Дата: 09.11.10 06:49
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>>>Еще раз повторяю — это просто фича содранная с Явы. Причем содранная по глупости.

N>>Не совсем так. Дизайнеры CLR и C# прекрасно понимали все издержки этого решения в Java. Но была бизнес-цель: облегчить миграцию кода, написанного на Java, на C#. И ради достижения этой цели пришлось, скрепя сердце, поддержать и эту фичу.
VD>Во уж не поверю. Сейчас они конечно именно так говорят. А тогда идея фик сбыла прикрутить к Яве события, т.е. сделать свою Яву но другую.
VD>Никто в здравом уме не переводил имеющиеся проекты с Явы на Шарп. Вот ГУЙ для винды делали — это да. Но для этого ничего портировать не надо было.

Переводили. В одной достаточно известной профессионализмом своих сотрудников компании был (ну может и есть) проект, в котором исходники на яве (которые разрабатывались отдельно) неким не сложным образом обрабатывались и получались исходники на шарпе. Была выписана библиотека с именами типов как они в библиотеке шарпа. И всё это, по словам сотрудников, работало весьма надёжно — сам видел и удивлялся.

Что там было с ковариантностью массивов мне неизвестно.
Help will always be given at Hogwarts to those who ask for it.
Re[12]: ковариантность в C#
От: _FRED_ Черногория
Дата: 09.11.10 07:00
Оценка:
Здравствуйте, Jack128, Вы писали:

J>>>>есть линковский Count(). Он вроде на ICollection тестирует, так что для массивов быстро работает..

_>>>Вся идея статической типизации состоит в том чтобы получать максимум возможных проверок компилятором в компайл-тайме. Это как физика — если размерности не сошлись, значит формула ошибочна.

_FR>>Это приведёт к чихарде с реализациями. Это слишком накладно поддерживать. Обсуждалось много лет назад ни один раз (например здесь
Автор: _FRED_
Дата: 09.05.07
). То же самое нужно и со стримами сделать (стрим на чтение только вперёд, с происвольным доступом и т.п.). В дотнете просто пошли другим путём, использовав Optional Features Pattern. Совершенно никаких проблем это не вызывает.


J>Любопытно, что за три года твое мнение по этому вопросу изменилось.


Совсем не изменилось. Просто из того, что "мне нравится" я не делаю выводов о том, что "так и должно быть"

J>Тогда ты сам предложил иерархию, аналогичную hi_octane Выглядит кста, вполне нормально, я б не отказался от такой реализации, вместо текущей.


Она по прежнему _выглядит_ лучше имеющейся. Но использовать и поддерживать её будет сложнее. Уже сейчас многие не могут понять, что лучше возвращать — IList/IEnumerable/массив. А там получается ещё запутаннее. Полезно всё-таки почитать FDG о целях, которые преследуются при написании API.
Help will always be given at Hogwarts to those who ask for it.
Re[13]: ковариантность в C#
От: Klatu  
Дата: 09.11.10 08:01
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Уже сейчас многие не могут понять, что лучше возвращать — IList/IEnumerable/массив.


Может я чего-то не понимаю, но по моему метод должен принимать максимально обощенный тип, а возвращать — максимально конкретизированный.
Re[8]: ковариантность в C#
От: _nn_ www.nemerleweb.com
Дата: 09.11.10 08:29
Оценка:
Здравствуйте, QrystaL, Вы писали:

K>>>Проблема в том, что хочется написать генерический метод просто и незатейливо — Foo(IList<T> vals)

K>>>А вот хрен тебе

VD>>Дык в чем проблема то? В 4.0 этот интерфейс ковариантный.


QL>Не совсем ))

QL>
QL>public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
QL>


Так надо полную картину описывать:
public interface IEnumerable<out T> : IEnumerable
public interface ICollection<T> : IEnumerable<T>, IEnumerable
public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable


public class ReadOnlyCollection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable


Итого только IEnumerable ковариантный
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[14]: ковариантность в C#
От: _FRED_ Черногория
Дата: 09.11.10 08:38
Оценка:
Здравствуйте, Klatu, Вы писали:

_FR>>Уже сейчас многие не могут понять, что лучше возвращать — IList/IEnumerable/массив.


K>Может я чего-то не понимаю, но по моему метод должен принимать максимально обощенный тип, а возвращать — максимально конкретизированный.

List

Ага, должен.

А как быть с методами интерфейсов, например — стоит ли диктовать, что следует вернуть (List<>, Collection<> или массив) или предоставить реализации самой выбрать наиболее удобный и оптимальный способ, обойдять IList<>-ом?

А как быть, когда некие внутренние условия изменились и возврат массива, который был дешёв в предыдущей версии сервиса сейчас уже несколько накладен?
Help will always be given at Hogwarts to those who ask for it.
Re[6]: ковариантность в C#
От: hi_octane Беларусь  
Дата: 09.11.10 08:40
Оценка: :)
N>Не совсем так. Дизайнеры CLR и C# прекрасно понимали все издержки этого решения в Java. Но была бизнес-цель: облегчить миграцию кода, написанного на Java, на C#. И ради достижения этой цели пришлось, скрепя сердце, поддержать и эту фичу.
Так ведь хранителем всех косяков Java был великий и ужасный J#. Неужели не могли там своих, косячных контейнеров наклепать что б джавистам было тепло у уютно? А в C# принести всё самое светлое, чистое и не упоротое непорочное
Re[11]: ковариантность в C#
От: hi_octane Беларусь  
Дата: 09.11.10 10:05
Оценка: 1 (1) +1
_FR>Это приведёт к чихарде с реализациями. Это слишком накладно поддерживать. Обсуждалось много лет назад ни один раз (например здесь
Автор: _FRED_
Дата: 09.05.07
). То же самое нужно и со стримами сделать (стрим на чтение только вперёд, с происвольным доступом и т.п.). В дотнете просто пошли другим путём, использовав Optional Features Pattern.

Это накладно поддерживать если поддерживаются несвязанные между собой интерфейсы. До тех пор пока наследование коллекций получается однонаправленное это поддерживать легко — реализуешь наиболее конкретный интерфейс который можешь и всё.

_FR>Совершенно никаких проблем это не вызывает.

Я протестую. Это голословно
На деле каждый косяк дизайна тянет за собой другие. Сейчас мы скатились до IEnumerable для чтения и IList для записи, т.е. по сути к тем же read-only и read-write коллекциям. А ковариантным интерфейсам (так лихо возвращаемся к теме топика) в CLR как бы и места нет — всё упёрлось в ICollection. Понятие контракта, проверяемого компилятором умерло, и ты сам подтверждаешь это ниже:

_FR>Вообще, в описании метода должно быть сказано, что метод будет делать с переданным списком: читать/добавлять/изменять и каким критериям должен удовлетворять этот IList<>.

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

_FR>Лёгко вам выводы делать. Попробуйте для начала спроектировать библиотеку, которую придётся поддерживать лет двадцать или тридцать и состоящую из десятков тысяч типов. Матюгов по поводу того, что кто-то наплодил туеву хучу интерфейсов вы услышите сильно чаще.

Если отбросить десятки тысяч притянутых за уши типов, то в сухом остатке получим 3 кривых интерфеса , из которых реально используются 2, а в foreach с linq вообще только один влазит, причём самый простой.

_FR>Как минимум, правильные гайдлайны требуют по одной (а тут, возможно, понадобится и по две кое-где) реализации интерфейса в стандартной библиотеке. У меня получилось 6 интерфейсов. Какие интерфейсы предложили бы вы и какие реализации к ним?

У меня тоже примерно 6, но почему-то других. Но тут много думать надо и много тестировать на реальных задачах. В конце концов компилятор мог бы сам генерировать и интерфейс с optional features (тот который сейчас IList) по списку поддерживаемых коллекцией read и write интерфейсов если нужда в Optional Features действительно есть. Что мне примерно видится более лучшим решением чем текущее — уже писал. Вот, красивее оформил, только <T> убрал чтоб проще читалось:

IEnumerable/IEnumerator
  MoveNext()
  Reset()
  Current

ICollection : IEnumerable
  Count

IIndexedCollection : ICollection
  IndexOf()
  this[] { get; }

IArray : IIndexedCollection
  this[] { set; }

IWriteableCollection : ICollection
  Add()
  Remove()
  Clear()

IList : IArray, IWriteableCollection
  InsertAt()
  RemoveAt()

И то без хорошего обдумывания коллективом умных людей. Чисто полагаясь на опыт матюкания на то что сейчас

_FR>Лучше примите, что есть — этим можно очень успешно и очень легко пользоваться.

С этим можно делать только то что привыкли, а вот IList<string> к IList<object> я по-прежнему привести не могу. Ждём неймспейс System.Collections.Covariant?
Re[12]: ковариантность в C#
От: _FRED_ Черногория
Дата: 09.11.10 10:41
Оценка:
Здравствуйте, hi_octane, Вы писали:

_>Это накладно поддерживать если поддерживаются несвязанные между собой интерфейсы. До тех пор пока наследование коллекций получается однонаправленное это поддерживать легко — реализуешь наиболее конкретный интерфейс который можешь и всё.


Посмотрим-посмотрим (ниже)

_FR>>Совершенно никаких проблем это не вызывает.

_>Я протестую. Это голословно

Может быть. Я говорю исходя из своего опыта, а не умозрительно. Может быть и "голо"

_>На деле каждый косяк дизайна тянет за собой другие. Сейчас мы скатились до IEnumerable для чтения и IList для записи, т.е. по сути к тем же read-only и read-write коллекциям. А ковариантным интерфейсам (так лихо возвращаемся к теме топика) в CLR как бы и места нет — всё упёрлось в ICollection.


Да, сейчас кажется, что с этим будут проблемы (нет ковариантной ридонли-коллекции) — но если не хватает только этого, то данную проблему решить не сложно без переделки BCL. Есть какие-то ещё серьёзные проблемы?

_>Понятие контракта, проверяемого компилятором умерло, и ты сам подтверждаешь это ниже:


Вот это ещё более голословно В чём-то — в вопросах коллекции — да, компилятор не может чего-то проверить. Но это слишком абстрактно :о))

_FR>>Вообще, в описании метода должно быть сказано, что метод будет делать с переданным списком: читать/добавлять/изменять и каким критериям должен удовлетворять этот IList<>.

_>Этак мы договоримся до того что dynamic подходит всем, а в описании метода должно быть сказано...

Так же не верно. Ещё раз: я не спорю с тем, что по-другому более красиво, но при этом и намного сложнее. Стоит ли полученная сложность красивости? Исходя из того, что проблем из-за некрасивости очень мало, стоит. То есть в вопросе коллекций мы имеем дело с некоей "локольной оптимизацией" и применять эту отпимизацию/упрощение сразху на всё как-то не спортивно. Надо понять, зачем это сделано и рассуждать о том, стоило ли оно того. А аргументы "а давайте сделаем так везде и получим полную ерунду" нас на верный путь не выведут.

Тут речь о размном ограничении. Разумность основана на балансе между количеством интерфейсов, типах и тому подобном. в первом фреймворке у списка были свойства IsFixedSize и IsReadOnly и мало кто знал, что они означают и что с ними делать, хотя в любой книжке было про это сказано. Моя модельнамного сложнее. А теперь ещё и IsFixedSize нет. в чём-то стало проще, в чём-то менее декларативно.

_FR>>Лёгко вам выводы делать. Попробуйте для начала спроектировать библиотеку, которую придётся поддерживать лет двадцать или тридцать и состоящую из десятков тысяч типов. Матюгов по поводу того, что кто-то наплодил туеву хучу интерфейсов вы услышите сильно чаще.

_>Если отбросить десятки тысяч притянутых за уши типов, то в сухом остатке получим 3 кривых интерфеса , из которых реально используются 2, а в foreach с linq вообще только один влазит, причём самый простой.

Ой, кажется это возражение? Но какое-то не продуктивное, извините. Даже не знаю, что с ним делать, как отвечать. Ну в самом деле. И для foreach IEnumerable не нужен, и в линке кой-где ICollection<> используется. А большего и не нужно. Зачем в линке IList<>

_FR>>Как минимум, правильные гайдлайны требуют по одной (а тут, возможно, понадобится и по две кое-где) реализации интерфейса в стандартной библиотеке. У меня получилось 6 интерфейсов. Какие интерфейсы предложили бы вы и какие реализации к ним?

_>У меня тоже примерно 6, но почему-то других. Но тут много думать надо и много тестировать на реальных задачах. В конце концов компилятор мог бы сам генерировать и интерфейс с optional features (тот который сейчас IList) по списку поддерживаемых коллекцией read и write интерфейсов если нужда в Optional Features действительно есть. Что мне примерно видится более лучшим решением чем текущее — уже писал. Вот, красивее оформил, только <T> убрал чтоб проще читалось:

Ага! А теперь, какие реализации этих интерфейсов вы бы предложили иметь в стандартной библиотеке?

_FR>>Лучше примите, что есть — этим можно очень успешно и очень легко пользоваться.

_>С этим можно делать только то что привыкли, а вот IList<string> к IList<object> я по-прежнему привести не могу. Ждём неймспейс System.Collections.Covariant?

А что там иметь-то? Кроме ридонли-коллекции? Если предложения?
Help will always be given at Hogwarts to those who ask for it.
Re[12]: ковариантность в C#
От: QrystaL Украина  
Дата: 09.11.10 11:06
Оценка: :))) :))
_>У меня тоже примерно 6, но почему-то других. Но тут много думать надо и много тестировать на реальных задачах.

Что скажете про C5?

Re[7]: ковариантность в C#
От: cvetkov  
Дата: 09.11.10 11:28
Оценка:
Здравствуйте, hi_octane, Вы писали:

_>Так ведь хранителем всех косяков Java был великий и ужасный J#. Неужели не могли там своих, косячных контейнеров наклепать что б джавистам было тепло у уютно?

своих массивов?
_> А в C# принести всё самое светлое, чистое и не упоротое непорочное
... << RSDN@Home 1.2.0 alpha 4 rev. 1227>>
Re[13]: ковариантность в C#
От: hi_octane Беларусь  
Дата: 10.11.10 09:33
Оценка:
QL>Что скажете про C5?
Впечатляет. Сразу почувствовал себя джуниором, который и коллекций-то не видел

Но есть один нюанс. Судя по схеме коллекции связаны между собой не тем read-only они или нет, а тем как они внутри устроены и какие сервисы дают. А устройств контейнеров может быть немеряно, вот и получается схема в которой интерфейсов столько же сколько реализаций. Получается что в приведенной схеме ковариантным будет опять IEnumerable, IDirectedEnumerable, ICollectionValue двух-трёх видов и, наверное, всё. А для того чтобы ковариантностью удобно было пользоваться той что есть, на интерфейсах и делегатах, надо организовать интерфейсы как-то иначе.
Re[14]: ковариантность в C#
От: QrystaL Украина  
Дата: 10.11.10 10:06
Оценка:
QL>>Что скажете про C5?
_>Впечатляет. Сразу почувствовал себя джуниором, который и коллекций-то не видел

_>Но есть один нюанс. Судя по схеме коллекции связаны между собой не тем read-only они или нет, а тем как они внутри устроены и какие сервисы дают. А устройств контейнеров может быть немеряно, вот и получается схема в которой интерфейсов столько же сколько реализаций. Получается что в приведенной схеме ковариантным будет опять IEnumerable, IDirectedEnumerable, ICollectionValue двух-трёх видов и, наверное, всё. А для того чтобы ковариантностью удобно было пользоваться той что есть, на интерфейсах и делегатах, надо организовать интерфейсы как-то иначе.


Они-то писались еще до 4-го фреймворка, так что вариантностью никто не заморачивался. В общем-то исходники открыты, можно их подпилить при желании...
Re[13]: ковариантность в C#
От: hi_octane Беларусь  
Дата: 10.11.10 11:24
Оценка:
_FR>Да, сейчас кажется, что с этим будут проблемы (нет ковариантной ридонли-коллекции) — но если не хватает только этого, то данную проблему решить не сложно без переделки BCL. Есть какие-то ещё серьёзные проблемы?
Тут согласен. Можно замутить набор интерфейсов более дружелюбных к ковариантности, и сделать существующие List, Array и т.п. их поддерживающими. Тут мне остро захотелось Duck Interfaces в CLR.

_FR>Вот это ещё более голословно В чём-то — в вопросах коллекции — да, компилятор не может чего-то проверить. Но это слишком абстрактно :о))

Так он может. Но ему не дают. Наверное можно через кодо-контракты optional features гарантировать, но по сравнению с ошибкой типизации — не айс.

_FR>Ага! А теперь, какие реализации этих интерфейсов вы бы предложили иметь в стандартной библиотеке?

Боюсь удивить не смогу Array : IArray, List : IList, LinkedList : IList, CollectionBase : IList, Queue : ICollection, Stack : ICollection. Где я облажался?

_FR>А что там иметь-то? Кроме ридонли-коллекции? Если предложения?

Ну с ридонли стоило бы начать, а там как попрёт. Например всякие View коллекции для биндинга, списки строк в гридах, и прочая лабуда, которая сейчас использует object, форматтеры, конвертеры, и прочую — вполне могли бы от ковариантности какой-то профит поиметь. Но сразу вывалить на гора концепцию "новый BCL over 9000 лучше старого", я конечно не возьмусь
Re[14]: ковариантность в C#
От: _FRED_ Черногория
Дата: 10.11.10 11:42
Оценка:
Здравствуйте, hi_octane, Вы писали:

_FR>>Да, сейчас кажется, что с этим будут проблемы (нет ковариантной ридонли-коллекции) — но если не хватает только этого, то данную проблему решить не сложно без переделки BCL. Есть какие-то ещё серьёзные проблемы?

_>Тут согласен. Можно замутить набор интерфейсов более дружелюбных к ковариантности, и сделать существующие List, Array и т.п. их поддерживающими. Тут мне остро захотелось Duck Interfaces в CLR.

Да нужны-то всего две вещи:

public interface IReadOnlyCollection<out T> : IEnumerable<T>
{
  int Count { get; }
}

public interface IReadOnlyList<out T> : IReadOnlyCollection<T>
{
  T this[int index] { get; }
}

public static class Sequence
{
  public static IReadOnlyCollection<T> AsReadOnlyCollection<T>(this ICollection<T> source) {
    return new ReadOnlyCollection<T>(source); // Это свой, а не стандартный, класс
  }

  public static IReadOnlyList<T> AsReadOnlyList<T>(this IList<T> source) {
    return new ReadOnlyList<T>(source);
  }
}


"сделать существующие List, Array и т.п. их поддерживающими" — не так уж и надо.

_FR>>Вот это ещё более голословно В чём-то — в вопросах коллекции — да, компилятор не может чего-то проверить. Но это слишком абстрактно :о))

_>Так он может. Но ему не дают. Наверное можно через кодо-контракты optional features гарантировать, но по сравнению с ошибкой типизации — не айс.

Ещё раз: речь о балансе тёмной и светлой стороны силы. Целиком уход в светлую в данном случвае чреват.

_FR>>Ага! А теперь, какие реализации этих интерфейсов вы бы предложили иметь в стандартной библиотеке?

_>Боюсь удивить не смогу Array : IArray, List : IList, LinkedList : IList, CollectionBase : IList, Queue : ICollection, Stack : ICollection. Где я облажался?

А где реализации IIndexedCollection и IWriteableCollection? Для чего они вообще нужны В вашей иерархии IIndexedCollection используется только в IArray, а IWriteableCollection используется только в IList, так какой смысл в том, что бы выделять их?

_FR>>А что там иметь-то? Кроме ридонли-коллекции? Если предложения?

_>Ну с ридонли стоило бы начать, а там как попрёт. Например всякие View коллекции для биндинга, списки строк в гридах, и прочая лабуда, которая сейчас использует object, форматтеры, конвертеры, и прочую — вполне могли бы от ковариантности какой-то профит поиметь.

Задачи биндинга ридонли не покроет, придётся дублировать ридонли-биндинг и не-ридонли.
Help will always be given at Hogwarts to those who ask for it.
Re[15]: ковариантность в C#
От: hi_octane Беларусь  
Дата: 10.11.10 13:03
Оценка:
_>>Боюсь удивить не смогу Array : IArray, List : IList, LinkedList : IList, CollectionBase : IList, Queue : ICollection, Stack : ICollection. Где я облажался?
_FR>А где реализации IIndexedCollection и IWriteableCollection? Для чего они вообще нужны
IWriteableCollection для коллекций которые не рассчитаны на доступ по индексу, но позволяют добавлять и удалять. Например HashSet/SortedSet, возможно коллекция DictionaryEntry у Dictionary.

_FR>В вашей иерархии IIndexedCollection используется только в IArray, а IWriteableCollection используется только в IList, так какой смысл в том, что бы выделять их?

Они удобны когда коллекцию использует программист, как способ получить какие-то гарантии от метода который он вызывает. А для того кто метод реализует — они дадут ограничения в рамках которых он может решать поставленную задачу. Например алгоритм выполняет над большим массивом операцию в несколько потоков одновременно. Ему принципиально гарантировать что все методы которые используют массив не будут менять там данные ни при каких обстоятельствах. Передача массива как IIndexedCollection может это обеспечить. Сейчас же типична ситуация когда передаём сам массив, и пишем коммент капсом. По сути гарантируя лишь что найдём крайнего, прозевавшего капс, когда всё поломается Ну на самый крайний случай оборачиваем массив в свой ReadOnlyArray, с this[]{get;}, но такая штука это трижды удар по скорости — один раз на косвенный вызов который не хочет инлайниться, и ещё раз на проверку границ массива, для которой у jit оптимизация работает только при непосредственно работе с массивом. Чувство прекрасного страдает, ковариантность в беде.

_FR>Задачи биндинга ридонли не покроет, придётся дублировать ридонли-биндинг и не-ридонли.

Есть контролы/ячейки грида которые только отображают контент. Таким хватит ридонли-биндинга, есть более сложные, им не хватит. Но т.к. writeable наследуется от read-only, то проблем из-за угла при биндинге я не жду. Зато будет гарантия что какой-нить джуниорописанный ListView, получив на вход коллекцию, не начнёт в ней элементы переставлять, в попытках отсортировать пузырьком.
Re[16]: ковариантность в C#
От: _FRED_ Черногория
Дата: 10.11.10 13:20
Оценка:
Здравствуйте, hi_octane, Вы писали:

_>>>Боюсь удивить не смогу Array : IArray, List : IList, LinkedList : IList, CollectionBase : IList, Queue : ICollection, Stack : ICollection. Где я облажался?

_FR>>А где реализации IIndexedCollection и IWriteableCollection? Для чего они вообще нужны
_>IWriteableCollection для коллекций которые не рассчитаны на доступ по индексу, но позволяют добавлять и удалять. Например HashSet/SortedSet, возможно коллекция DictionaryEntry у Dictionary.

Я просто не увидел этого в первоначальном списке

_FR>>В вашей иерархии IIndexedCollection используется только в IArray, а IWriteableCollection используется только в IList, так какой смысл в том, что бы выделять их?

_>Они удобны когда коллекцию использует программист, как способ получить какие-то гарантии от метода который он вызывает. А для того кто метод реализует — они дадут ограничения в рамках которых он может решать поставленную задачу. Например алгоритм выполняет над большим массивом операцию в несколько потоков одновременно. Ему принципиально гарантировать что все методы которые используют массив не будут менять там данные ни при каких обстоятельствах. Передача массива как IIndexedCollection может это обеспечить.

Пардон, но обеспечить это можно и сейчас, пользуясь IList<> как типом параметра метода и передавая в метод, требующий IList<>, стандартный new ReadOnlyCollection<>.

Вы какую задачу всё-таки пытаетесь решить новой иерархией интерфейсов?

Например, как сейчас — если метод принимает IList<> то из описания того, что метод делает более чем понятно, будет ли метод коллекцию менять. Если не понятно или вы не доверяете описанию, то передайте в метод ReadOnlyCollection<>-обёртку над вашим списком. Это гарантирует (в большинстве случаев) то, что ваша коллекция останется неизменной.

Спрошу ещё так: можете ли вы показать какой-нить профит от того, что метод объявлен как
void MyMethod(IIndexedCollection<int> items) {}

по сравнению с
void MyMethod(IList<int> items) {}

Что компилятор сможет вам подсказать, от какой ошибки уберечь и в каком случае

В контексте данного топика мне казалось, что мы сетуем на невозможность использовать вариантность с существующими коллекциями — но в вашей версии интерфейсов вариантен только ICollection<>. Всё остальное же не ковариантно.

_>Сейчас же типична ситуация когда передаём сам массив, и пишем коммент капсом. По сути гарантируя лишь что найдём крайнего, прозевавшего капс, когда всё поломается

Нет, давайте рассматривать конкретные примеры кода. "передаём массив" ни о чём не говорит, важно — какого типа параметр. Тоже массив? или IList<>? Покажите на примере двух методов выше, в чём профит от ваших интерфейсов.

_>Ну на самый крайний случай оборачиваем массив в свой ReadOnlyArray, с this[]{get;}, но такая штука это трижды удар по скорости — один раз на косвенный вызов который не хочет инлайниться, и ещё раз на проверку границ массива, для которой у jit оптимизация работает только при непосредственно работе с массивом. Чувство прекрасного страдает, ковариантность в беде.


Это ерунда, а не удар по скорости. Мы же не на спичках экономим? По сравнению, например, а API линка, которое требует создание делегатов это будет всё мнгновенно. или, может, цель которуй вы преследуете именно скорость? Ответье.

_FR>>Задачи биндинга ридонли не покроет, придётся дублировать ридонли-биндинг и не-ридонли.

_>Есть контролы/ячейки грида которые только отображают контент. Таким хватит ридонли-биндинга, есть более сложные, им не хватит. Но т.к. writeable наследуется от read-only, то проблем из-за угла при биндинге я не жду. Зато будет гарантия что какой-нить джуниорописанный ListView, получив на вход коллекцию, не начнёт в ней элементы переставлять, в попытках отсортировать пузырьком.

Если цели не связаны с ковариантностью — да, такое возможно (правда пока не ясно зачем). если со скоростью (экономия на косвенных выховах) то по сравнению с биндингом вы опять никакого преимущества не получите
Help will always be given at Hogwarts to those who ask for it.
Re[14]: ковариантность в C#
От: QrystaL Украина  
Дата: 10.11.10 13:41
Оценка:
Здравствуйте, hi_octane, Вы писали:
_>Впечатляет. Сразу почувствовал себя джуниором, который и коллекций-то не видел

Та да, наворотили. А вообще интересно было бы сравнить с иерархией коллекций/интерфейсов коллекций в других языках (например, Scala или что-то подобное)
Re[17]: ковариантность в C#
От: hi_octane Беларусь  
Дата: 10.11.10 21:23
Оценка: 3 (1)
_FR>Я просто не увидел этого в первоначальном списке
А я в первоначальном списке их и не писал

_FR>Пардон, но обеспечить это можно и сейчас, пользуясь IList<> как типом параметра метода и передавая в метод, требующий IList<>, стандартный new ReadOnlyCollection<>.

_FR>Вы какую задачу всё-таки пытаетесь решить новой иерархией интерфейсов?
_FR>Например, как сейчас — если метод принимает IList<> то из описания того, что метод делает более чем понятно, будет ли метод коллекцию менять.
Вот не надо описаний моё мнение на этот счёт однозначное: если весь контракт описание — то он обязательно будет нарушен. Если не сразу, то после второго рефакторинга точно. А то договоримся до того что readonly с const не нужны — описания хватит. И входных проверок аргументов не надо, в описании сказать, и пусть валится если null передали, или ерунду какую.

_FR>Если не понятно или вы не доверяете описанию, то передайте в метод ReadOnlyCollection<>-обёртку над вашим списком. Это гарантирует (в большинстве случаев) то, что ваша коллекция останется неизменной.

Понимаю это и передаю. Но на кой чёрт такая гарантия если оно свалится в рантайме в тот момент когда эту коллекцию начнут менять — что ошибка в рантайме от того что коллекцию таки наменяли, что ошибка рантайме в тот момент когда её попытались поменять. Разве что во вотором случае, возможно, проще уловимая. Но это ошибка рантайма, а мог быть надёжный контракт компайл-тайма.

_FR>Что компилятор сможет вам подсказать, от какой ошибки уберечь и в каком случае

Да что-ж непонятного-то? Компилятор просто не даст скомпилировать ни одну операцию изменения read-only коллекции. В моём случае метод гарантированно не свалится в рантайме с NotSupportedException, просто потому что ни одного метода записи у read-only интерфейсов нет.

_FR>В контексте данного топика мне казалось, что мы сетуем на невозможность использовать вариантность с существующими коллекциями — но в вашей версии интерфейсов вариантен только ICollection<>. Всё остальное же не ковариантно.

На 2010-й студии не проверял, но ковариантной по идее должна быть вся read-only иерархия. Как доберусь до компа с 2010-й — проверю, смогу сказать точнее.

_>>Сейчас же типична ситуация когда передаём сам массив, и пишем коммент капсом. По сути гарантируя лишь что найдём крайнего, прозевавшего капс, когда всё поломается

_FR>Нет, давайте рассматривать конкретные примеры кода. "передаём массив" ни о чём не говорит, важно — какого типа параметр. Тоже массив? или IList<>? Покажите на примере двух методов выше, в чём профит от ваших интерфейсов.
Сейчас практически нет разницы массив или IList. Вот на примере метода
void MyMethod(IList<int> items) {}

Реально ли тому кому нужно реализовать метод с этой сигнатурой определить, можно ему писать в items или нет? А тому кто собрался метод вызывать, реально ли определить, будет реализация MyMethod писать в items или нет? А если будет, то можно ли туда передать массив, или в items могут добавить пару элементов? А если MyMethod — метод интерфеса, то что насчёт возможных реализаций, все ли они ведут себя одинаково?
А если запишем с массивом:
void MyMethod(int[] items) {}

Намного ли больше можем сказать? Ну допустим Add/Remove/Clear для items вызвать не получится — уже лучше. В остальном — всё тоже что и для IList. Мы даже не знаем, вызывающая сторона или вызываемая должна быть исправлена если вылетает NotSupportedException.

А на примере моего:
void MyMethod(IIndexedCollection<int> items) {}

Тот кто вызывает метод — знает на 100% что туда можно передать массив и что в массив не будут писать. Тот кто реализует метод — как бы ни старался, в items не запишет. Хоть в 10-потоках items используй, и передавай её самым разным методам, глюков связанных с тем что кто-то начал портить расшаренные данные — не будет. Это ли не profit?
Теперь для:
void MyMethod(IArray<int> items)

Тот кто реализует метод — знает, что получает массив и что писать в него можно. Попытается добавить/удалить — методов Add/Remove/Clear у IArray нет, так что не скомпилируется. Если мне такой метод вызывать надо — то я автоматом знают что передать в него можно Array или List, и оно будет работать с ними одинаково. Я знаю что если мне нужно сохранить items в неизменном виде, то нужно в MyMethod передать копию.

В обоих случаях никаких NotSupportedException я не получу. Им просто неоткуда взяться, независимо от воли программиста реализующего MyMethod.

_FR>Это ерунда, а не удар по скорости. Мы же не на спичках экономим? По сравнению, например, а API линка, которое требует создание делегатов это будет всё мнгновенно. или, может, цель которуй вы преследуете именно скорость? Ответье.

Хочу всё сразу: экономии на .AsReadOnly(), на ассертах, на ловле исключений в рантайме, на комментариях к методам и на тестах. Будь иерархия коллекций чуть лучше спроектирована — ушла бы куча внешне разнородных косяков. И ковариантность получше работала бы, и контракты между методами и интерфесами построже, может и в скорости где-то выиграли. И пока ни одного внятного обоснования почему существующая иерархия IEnumerable->ICollection->IList именно такая, кроме внешне убедительно выглядяшего (а при ближайшем рассмотрении — не очень) текста из "Java Collections API Design FAQ" я не нашёл. Остаётся верить что создатели текущей иерархии BCL что-то знают, но пока примеров этого "что-то", которые бы однозначно доказывали что текущая иерархия заруливает даже вариант который можно придумать за 5 минут на коленке — не вижу
Re[18]: ковариантность в C#
От: _FRED_ Черногория
Дата: 10.11.10 21:47
Оценка: -1
Здравствуйте, hi_octane, Вы писали:

_FR>>Пардон, но обеспечить это можно и сейчас, пользуясь IList<> как типом параметра метода и передавая в метод, требующий IList<>, стандартный new ReadOnlyCollection<>.

_FR>>Вы какую задачу всё-таки пытаетесь решить новой иерархией интерфейсов?
_FR>>Например, как сейчас — если метод принимает IList<> то из описания того, что метод делает более чем понятно, будет ли метод коллекцию менять.
_>Вот не надо описаний моё мнение на этот счёт однозначное: если весь контракт описание — то он обязательно будет нарушен.

А почему влруг "весь"? Давайте всё-таки не срываться на практикуу не профильных форумов, а то станет вдруг не интересно. Да, описание в доке это не вовсе не тоже самое самое, что описание, проверяемое компилятором. В вашем ответе я не увидел примера, когда компилятор сумел бы подсказать мне об ошибке. Почему не сумел — не было или не разглядел? Может, уточните?

_>Если не сразу, то после второго рефакторинга точно. А то договоримся до того что readonly с const не нужны — описания хватит. И входных проверок аргументов не надо, в описании сказать, и пусть валится если null передали, или ерунду какую.


+1. Тогда показывайте пример, когда проверка компилятора даст профит.

_FR>>Если не понятно или вы не доверяете описанию, то передайте в метод ReadOnlyCollection<>-обёртку над вашим списком. Это гарантирует (в большинстве случаев) то, что ваша коллекция останется неизменной.

_>Понимаю это и передаю. Но на кой чёрт такая гарантия если оно свалится в рантайме в тот момент когда эту коллекцию начнут менять — что ошибка в рантайме от того что коллекцию таки наменяли, что ошибка рантайме в тот момент когда её попытались поменять. Разве что во вотором случае, возможно, проще уловимая. Но это ошибка рантайма, а мог быть надёжный контракт компайл-тайма.

Если "оно свалится в рантайме", значит контракт не-ридонли, правильно? И тогда наши размышления о невозможности проверки кормпилятором некоторых условий пусты — не находите?

_FR>>Что компилятор сможет вам подсказать, от какой ошибки уберечь и в каком случае

_>Да что-ж непонятного-то? Компилятор просто не даст скомпилировать ни одну операцию изменения read-only коллекции. В моём случае метод гарантированно не свалится в рантайме с NotSupportedException, просто потому что ни одного метода записи у read-only интерфейсов нет.

А код-то или псевдо-код (хотя, по моему представлению, и код должен быть нормальный) какой показать сумеете? Почему нет?

_FR>>В контексте данного топика мне казалось, что мы сетуем на невозможность использовать вариантность с существующими коллекциями — но в вашей версии интерфейсов вариантен только ICollection<>. Всё остальное же не ковариантно.

_>На 2010-й студии не проверял, но ковариантной по идее должна быть вся read-only иерархия. Как доберусь до компа с 2010-й — проверю, смогу сказать точнее.

А всё очень просто, благодаря нотации принятой в шарпе: out и in — видно, что IndexOf(T) (а этот метод должен принимать параметр, хоть вы этого и не указали) есть "in", но ни как не "out".

_>>>Сейчас же типична ситуация когда передаём сам массив, и пишем коммент капсом. По сути гарантируя лишь что найдём крайнего, прозевавшего капс, когда всё поломается

_FR>>Нет, давайте рассматривать конкретные примеры кода. "передаём массив" ни о чём не говорит, важно — какого типа параметр. Тоже массив? или IList<>? Покажите на примере двух методов выше, в чём профит от ваших интерфейсов.
_>Сейчас практически нет разницы массив или IList. Вот на примере метода


Приведите пожалуйста пример такого метода MyMethod, для которого было бы важно, IList<> в него передали или что-то другое (IIndexedCollection<>)? Просто тупо код метода, наиболее разумного — сумеете?

_FR>>Это ерунда, а не удар по скорости. Мы же не на спичках экономим? По сравнению, например, а API линка, которое требует создание делегатов это будет всё мнгновенно. или, может, цель которуй вы преследуете именно скорость? Ответье.

_>Хочу всё сразу:

"Нет, сынок, это фантастика" — вы вообще рекламу по ящику смотрите? Про SRP слышали? Сразу всего вместе для всего не бывает. Вот если постараться и отделить что-то от чего можно ещё удовлетворить и одно и второе. В том, что естль сейчас видно, как всё удовлетворяется. Как это будет в вашей моделе пока не видно — что бы предлдожите на замену IBindingList? Опять две коллекции? Или больше, чем две?
Help will always be given at Hogwarts to those who ask for it.
Re[8]: ковариантность в C#
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.11.10 17:21
Оценка:
Здравствуйте, nikov, Вы писали:

_>>Кому надо с Java перешли, поэтому к 4-му фреймворку могли бы ее отключить


N>Я уверен, что до сих пор в продакшене есть C# код (возможно, мигрировавший с Java), который использует эту фичу. Его нельзя вот просто так сломать.


Если хочется, то можно почти все. Например, можно ввести опцию компиляции (для совместимости), или прагму. Ворнинги о скором устранении фичи тоже хорошо помогли бы.

Так что тут просто нет желания это делать, не возможности.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: ковариантность в C#
От: nikov США http://www.linkedin.com/in/nikov
Дата: 18.11.10 17:31
Оценка:
Здравствуйте, VladD2, Вы писали:

N>>Я уверен, что до сих пор в продакшене есть C# код (возможно, мигрировавший с Java), который использует эту фичу. Его нельзя вот просто так сломать.


VD>Если хочется, то можно почти все. Например, можно ввести опцию компиляции (для совместимости), или прагму.

А при чём здесь опция компиляции, если это фича рантайма? Если хочешь просто запретить такие преобразования в своём коде в compile time — пожалуйста, напиши правило для FxCop.

VD>Ворнинги о скором устранении фичи тоже хорошо помогли бы.

На многих проектах используется опция Treat warnings as errors. Для них появляение нового warning-a — это breaking change. Если warning не связан с вероятным наличием логической ошибки в коде — то его добавлять очень нежелательно.

VD>Так что тут просто нет желания это делать, не возможности.

Да, нет желания усложнять жизнь пользователям, и повышать для них эффективную стоимость использования компилятора C# на их текущих проектах.
Re[10]: ковариантность в C#
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.11.10 18:02
Оценка:
Здравствуйте, nikov, Вы писали:

N>А при чём здесь опция компиляции, если это фича рантайма?


Любая фича рантайма может быть выключена. Главное чтобы код на нее не рассчитывал.
Выключается же оптимизация джита банальным атрибутом?

N>Если хочешь просто запретить такие преобразования в своём коде в compile time — пожалуйста, напиши правило для FxCop.


Не, не хочу. Хочу чтобы не было соответствующего аверхэда.

VD>>Ворнинги о скором устранении фичи тоже хорошо помогли бы.

N>На многих проектах используется опция Treat warnings as errors. Для них появляение нового warning-a — это breaking change. Если warning не связан с вероятным наличием логической ошибки в коде — то его добавлять очень нежелательно.

Ничего страшно, кому надо вюключат конкретный ворнинг. К тому же это одно из возможных решений, а не единственное.

VD>>Так что тут просто нет желания это делать, не возможности.

N>Да, нет желания усложнять жизнь пользователям, и повышать для них эффективную стоимость использования компилятора C# на их текущих проектах.

Жизнь пользователя нисколько не усложнится. Эту фичи почти никто не использует.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.