Pull to refresh

Comments 8

Это здорово, конечно, но зачем это здесь? Что нового, того что нет в документации, можно узнать из этой публикации?

например я узнал что это не синтаксический сахар , очень был уверен что это он , а тут оказывается разные типы

Во-первых это, конечно, есть в документации. Во-вторых, синтаксис валуетуплов это сахар

UFO landed and left these words here

Неделя началась с постов про C#, что ж.

кортежи определяются с неограниченным количеством элементов.

Здесь было бы уместно сказать, что кортеж это просто сахар над System.ValueTuple<...>. И что у этого есть проблема, такая же как у System.Action и System.Func -- конечное число комбинаций.
Так если ваш кортеж/тапл содержит до 7 элементов, под это все выписаны отдельные дженерики (включая кортеж размера 0 и 1, хотя создать их с помощь сахара нельзя).
А дальше начинается фигня, потому что ValueTuple`8 содержит 7 дженерик полей, а 8-ое зарезервировано под такой же кортеж. Поэтому кортеж из 8 элементов это тип, который содержит 7 первых элементов и 8-ой, обернутый в 1-кортеж. А если у вас 10 элементов, то это все равно ValueTuple`8,но последний элемент это 3-кортеж, и так далее.
См примеры на SharpLab и имплементацию на GitHub.

А еще ваш кортеж реализует ITuple, такой же интерфейс реализуют и обычные System.Tuple<>. Поэтому кортежи можно проверять на ITuple, который имеет длину и индексатор типа object. Эта фича используется, кстати, при pattern-matching.
Если у вас object o is (int a, int b), то проверка идет не на ValueTuple а на интерфейс, а значит и Tuple тоже подойдет. Конрад Кокоса, кажется, пригорал по этому поводу в одном из твитов, говорил что вместо такого паттерна проще чекать по GetType и потом явно приводить тип -- получалось быстрее, чем доставать из интерфейса objects и потом каждый распаковывать в нужный тип. Ссылки на твит не найду, но вот ссылка на пример на ShapLab, где видна разница. Не силен в asm, но кажется даже JIT-код содержит вызовы всяких Unbox, что вряд ли показатель быстрого кода.
Зато если у вас свой тип реализует ITuple, он должен честно паттерн-матчистя и деконструироваться (но я не првоерял).

Ах да, в топике про деконструкцию хорошо бы было упомянуть и деконструкцию произвольных типов по сигнатуре public void Deconstruct(out T1 p1, out T2 p2, /* .. */). Можно как инстанс метод, можно как экстеншн метод навесить на чужой тип. После этого работает (T1 p1, T2 p2) = myTypeInstance, ну и весь синтаксический сахар паттернов. Хорошо сочетается с foreach.

Не уверен, что этим кто-то особо пользуется. По крайней мере - в коде разных людей я ValueTuple (как и, в принципе, вообще Tuple) не встречал, да и не вижу смысла в этом. Надо передать функции много параметров? Создай объект. Надо вернуть много результатов? Создай объект или, если нужно просто значение и успешность операции, то верни bool, а через out выведи результат.

Sign up to leave a comment.

Articles