Является ли тестирование универсальных коллекций на ссылочное равенство в C# глупой идеей?

Я реализую частный случай неизменяемого словаря, который для удобства реализует IEnumerable<KeyValuePair<Foo, Bar>>. Операции, которые обычно изменяют словарь, вместо этого должны возвращать новый экземпляр.

Все идет нормально. Но когда я пытаюсь написать модульный тест в стиле Fluent для класса, я обнаруживаю, что ни одна из двух библиотек Fluent Assert, которые я пробовал (Should и Fluent Assertions) поддерживают операцию NotBeSameAs() для объектов, которые реализуют IEnumerable -- нет, если вы сначала не примените их к Object.

Когда я впервые столкнулся с этим, с Должен, я предположил, что это была просто дыра в структуре, но когда я увидел, что у Fluent Asserts есть такая же дыра, я подумал, что (поскольку я относительный новичок в C #) Я мог упустить что-то концептуальное в отношении коллекций C# — автор книги Должен подразумевать это, когда Я подал заявку.

Очевидно, есть и другие способы проверить это - привести к Object и использовать NotBeSameAs(), просто использовать Object.ReferenceEquals, что угодно, но если есть веская причина не делать этого, я хотел бы знать, что это такое.


person David Moles    schedule 13.03.2013    source источник
comment
Кстати, вы смотрели на неизменяемые коллекции MS? nuget.org/packages/Microsoft.Bcl.Immutable   -  person Jon Skeet    schedule 13.03.2013
comment
@JonSkeet Мммм. Какую доброту ты нам показываешь. Спасибо.   -  person spender    schedule 13.03.2013
comment
Любой тип - это Object, зачем вам нужно приводить?   -  person Jodrell    schedule 13.03.2013
comment
@Jodrell - вам нужно привести его, потому что фреймворк реализован с точки зрения методов расширения, и если вы его не примените, вы получите более конкретный метод расширения для IEnumerable, который, в отличие от менее конкретного для Object, не не поддерживает операцию NotBeSameAs().   -  person David Moles    schedule 13.03.2013
comment
@JonSkeet Выглядит потрясающе, но лицензия, кажется, запрещает использовать его в рабочем коде? (Кроме того, мой первоначальный вопрос остается в силе - я бы хотел использовать неизменяемые коллекции для внутренней реализации, но мне все же хотелось бы, чтобы более ограниченный объект-оболочка вокруг них реализовывал IEnumerable.)   -  person David Moles    schedule 13.03.2013


Ответы (2)


IEnumerable<T> не обязательно является реальным объектом. IEnumerable<T> гарантирует, что вы можете перечислить его состояния. В простых случаях у вас есть класс контейнера, такой как List<T>, который уже материализован. Затем вы можете сравнить адреса обоих списков. Однако ваш IEnumerable<T> может также указывать на последовательность команд, которая будет выполняться после перечисления. В основном конечный автомат:

public IEnumerable<int> GetInts()
{
    yield return 10;
    yield return 20;
    yield return 30;
}

Если вы сохраните это в переменной, у вас не будет сопоставимого объекта (все является объектом, поэтому вы делаете... но это не имеет смысла):

var x = GetInts();

Ваше сравнение работает только для материализованных ( .ToList() или .ToArray() ) IEnumerables, потому что эти конечные автоматы были оценены, и их результаты были сохранены в коллекции. Так что да, библиотека на самом деле имеет смысл, если вы знаете, что материализовали IEnumerables, вам нужно будет сделать это знание общедоступным, приведя их к Object и вызвав нужную функцию для этого объекта "вручную".

person nvoigt    schedule 13.03.2013

Кроме того, что предложил Джон Скит, взгляните на эту статью MSDN за февраль 2013 года от Теда Ньюарда:

Коллекции .NET, часть 2. Работа с C5

Неизменяемые (защищенные) коллекции

С появлением функциональных концепций и стилей программирования большое внимание стало уделяться неизменяемым данным и неизменяемым объектам, в основном потому, что неизменяемые объекты предлагают много преимуществ по сравнению с параллелизмом и параллельным программированием, а также потому, что многие разработчики находят неизменяемые объекты легче понять и рассуждать. Таким образом, следствием этой концепции является концепция неизменяемых коллекций — идея о том, что независимо от того, являются ли объекты внутри коллекции неизменяемыми, сама коллекция фиксирована и не может изменять (добавлять или удалять) элементы в коллекции. (Примечание. Предварительный просмотр неизменяемых коллекций, выпущенных на NuGet, можно найти в блоге MSDN Base Class Library (BCL) по адресу bit.ly. /12AXD78.)

В нем описывается использование библиотеки с открытым исходным кодом под названием C5. См. http://itu.dk/research/c5/.

person pero    schedule 13.03.2013
comment
Я взглянул на C5, но у меня было много странных проблем с приведением, пытаясь заставить его взаимодействовать с System.Collections.Generic. (В какой-то момент, если я буду достаточно разочарован готовыми коллекциями, возможно, я попробую еще раз и превратю эти проблемы в вопросы StackOverflow....) - person David Moles; 13.03.2013