Re[26]: Quiff
От: Qbit86 Кипр
Дата: 17.09.20 14:16
Оценка: 111 (1)
Здравствуйте, Sinclair, Вы писали:

Q>>Я бы читал: «Элвис-присваивание».

S>Эмм, почему?

Родственные операторы типа ?? и ?. в C#, Kotlin и им подобных называются (традиционно/неформально) Elvis operator: «It resembles an emoticon of Elvis Presley with his quiff.»
Глаза у меня добрые, но рубашка — смирительная!
Re[31]: Welcome to C# 9.0
От: Ночной Смотрящий Россия  
Дата: 17.09.20 14:16
Оценка:
Здравствуйте, Serginio1, Вы писали:

НС>>По той что анонимные типы были придуманы для конкретной задачи ad-hoc типов в запросах, и там мутабельность ен нужна.

S>Ну анонимные типы используются не только в запросах.

Но придумали их именно для этого, и при разработке их дизайна руководствовались именно этим.

S>Для большинства задач эта мутабельность и не нужна.


Не нужна — не делай, никто не заставляет. Аргумент про таинственный Васек вредителей мягко говоря слабенький
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[29]: Welcome to C# 9.0
От: rameel https://github.com/rsdn/CodeJam
Дата: 17.09.20 14:19
Оценка:
Здравствуйте, Silver_S, Вы писали:

S_S>2) Если у тебя C# 8, и по другому работает. А у меня предыдущая версия, так работает (readonly только на struct можно ставить). В любом случае так не должно быть — ненадежная фича.


Просчитались, когда релизили 7 версию, потом исправились. Такие же защитные копии будут создаваться, например, и для ReadOnlySpan и на foreach, и в списках, да везде где есть возврат или прием аргументов толстых структур, если не озаботиться заранее, так что не только в in засада, здесь нужен соответствующий анализ и оптимизации от джита, способный все это устранить (кое-какие работы ведутся по устранению лишних клонирований, частично кое-что уже внедрено в современный Core). Хотя многое можно было бы сделать и на стороне рослина.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[30]: Welcome to C# 9.0
От: Silver_S Ниоткуда  
Дата: 17.09.20 14:47
Оценка:
Здравствуйте, rameel, Вы писали:

S_S>>2) Если у тебя C# 8, и по другому работает. А у меня предыдущая версия, так работает (readonly только на struct можно ставить). В любом случае так не должно быть — ненадежная фича.


R>Просчитались, когда релизили 7 версию, потом исправились. Такие же защитные копии будут создаваться, например, и для ReadOnlySpan и на foreach, и в списках, да везде где есть возврат или прием аргументов толстых структур, если не озаботиться заранее, так что не только в in засада, здесь нужен соответствующий анализ и оптимизации от джита, способный все это устранить (кое-какие работы ведутся по устранению лишних клонирований, частично кое-что уже внедрено в современный Core). Хотя многое можно было бы сделать и на стороне рослина.


Защитную копию они могли создавать только одну, и все вызовы делать к ней. Поведение будет другое — изменения будут в ней накапливаться. Ну и нормально.
То же самое что вызов без "in" — тоже одна копия, в которой все накапливается. Сомнительно что у кого-то такое по задумке в коде — предполагает что, на каждое обращение создается копия (что изменения не накапливаются).
А в таком виде я бы не рискнул "in" использовать. Проще для "ref" вручную проверить — нет ли модификаций.
Re[30]: Welcome to C# 9.0
От: AlexRK  
Дата: 17.09.20 14:51
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>По той что анонимные типы были придуманы для конкретной задачи ad-hoc типов в запросах, и там мутабельность ен нужна.


А почему не нужна-то? Кто это сказал?

Очень даже бывает нужна, какой-нибудь флаг выставить в процессе обработки.

Как ты там говоришь, "сделали анонимные типы тем самым убогими", верно?
Re[31]: Welcome to C# 9.0
От: rameel https://github.com/rsdn/CodeJam
Дата: 17.09.20 14:56
Оценка:
Здравствуйте, Silver_S, Вы писали:

S_S>Защитную копию они могли создавать только одну, и все вызовы делать к ней. Поведение будет другое — изменения будут в ней накапливаться. Ну и нормально.

В случае с in — да, но это к команде рослина, можно issue завести.

ЗЫ. Могли бы warning хотя бы добавить, согласен
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[31]: Welcome to C# 9.0
От: rameel https://github.com/rsdn/CodeJam
Дата: 17.09.20 15:01
Оценка:
Здравствуйте, Silver_S, Вы писали:

S_S>То же самое что вызов без "in" — тоже одна копия, в которой все накапливается. Сомнительно что у кого-то такое по задумке в коде — предполагает что, на каждое обращение создается копия (что изменения не накапливаются).

А по поводу кода, странно, что программист in втыкает, зная, что будет копия создаваться in — он для ридонли структур или ридонли-мемберов
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[31]: Welcome to C# 9.0
От: Ночной Смотрящий Россия  
Дата: 17.09.20 16:23
Оценка:
Здравствуйте, AlexRK, Вы писали:

НС>>По той что анонимные типы были придуманы для конкретной задачи ad-hoc типов в запросах, и там мутабельность ен нужна.

ARK>А почему не нужна-то? Кто это сказал?

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

ARK>Очень даже бывает нужна, какой-нибудь флаг выставить в процессе обработки.


Заведи новый тип, в который включи старый отдельным свойством. let примерно так и работает

ARK>Как ты там говоришь, "сделали анонимные типы тем самым убогими", верно?


Не надо приписывать мне того, чего я не говорил, некрасиво.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[32]: Welcome to C# 9.0
От: AlexRK  
Дата: 17.09.20 16:36
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>>>По той что анонимные типы были придуманы для конкретной задачи ad-hoc типов в запросах, и там мутабельность ен нужна.

ARK>>А почему не нужна-то? Кто это сказал?
НС>На тот момент в той задаче — была не нужна. В отличие от рекордов, которые снаружи совершенно обычный класс, анонимные типы штука весьма специфичная.

Специфичная, но не в контексте потребности мутабельности.

ARK>>Очень даже бывает нужна, какой-нибудь флаг выставить в процессе обработки.

НС>Заведи новый тип, в который включи старый отдельным свойством. let примерно так и работает

Ясное дело. Вместо изменения делается новый объект. Только вот для этого надо написать гораздо больше кода. Хммм, что-то мне это напоминает, уж не рассуждения ли о необходимости мутабельных полей в рекордах... Да не, бред какой-то.

ARK>>Как ты там говоришь, "сделали анонимные типы тем самым убогими", верно?

НС>Не надо приписывать мне того, чего я не говорил, некрасиво.

Ну, раз ты считаешь рекорды без возможности мутации "убогими", то и анонимные типы ровно в той же степени "убоги".
И там, и там можно найти случаи, когда мутабельность кому-то нужна. И там, и там без нее легко можно обойтись. Твои рассуждения в равной степени применимы в обоих случаях.
Re[33]: Welcome to C# 9.0
От: Ночной Смотрящий Россия  
Дата: 17.09.20 18:14
Оценка: +1
Здравствуйте, AlexRK, Вы писали:

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

ARK>Специфичная, но не в контексте потребности мутабельности.

Возможно. К анонимным типам вообще много претензий.

ARK>>>Очень даже бывает нужна, какой-нибудь флаг выставить в процессе обработки.

НС>>Заведи новый тип, в который включи старый отдельным свойством. let примерно так и работает
ARK>Ясное дело. Вместо изменения делается новый объект. Только вот для этого надо написать гораздо больше кода.

Если используешь query syntax — не особо.

ARK> Хммм, что-то мне это напоминает, уж не рассуждения ли о необходимости мутабельных полей в рекордах... Да не, бред какой-то.


Тебя не поймешь. Анонимные типы иммутабельны — плохо. Сделали рекордам возможность быть мутабельными — опять плохо.

ARK>Ну, раз ты считаешь рекорды без возможности мутации "убогими", то и анонимные типы ровно в той же степени "убоги".


Нет. Потому что у анонимных типов намного уже сфера применения. А рекорды это ровно те же классы в плане применимости, просто синтаксический сахар над ними, там мутабельность нужна намного сильнее.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[34]: Welcome to C# 9.0
От: AlexRK  
Дата: 17.09.20 18:19
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Тебя не поймешь. Анонимные типы иммутабельны — плохо. Сделали рекордам возможность быть мутабельными — опять плохо.


Я за максимальную иммутабельность везде. Про мутабельность это я провел параллель — если стоять на позиции "мутабельность нужна", то надо равным образом и про анонимные типы говорить.

ARK>>Ну, раз ты считаешь рекорды без возможности мутации "убогими", то и анонимные типы ровно в той же степени "убоги".

НС>Нет. Потому что у анонимных типов намного уже сфера применения. А рекорды это ровно те же классы в плане применимости, просто синтаксический сахар над ними, там мутабельность нужна намного сильнее.



Будет весело, если они в RC2 мутабельность эту уберут.
Re[35]: Welcome to C# 9.0
От: Ночной Смотрящий Россия  
Дата: 17.09.20 18:28
Оценка: +1
Здравствуйте, AlexRK, Вы писали:

НС>>Тебя не поймешь. Анонимные типы иммутабельны — плохо. Сделали рекордам возможность быть мутабельными — опять плохо.

ARK>Я за максимальную иммутабельность везде.

Это я уже понял. Но подход с мутабельными классами тоже имеет право на жизнь. И не дело проектировать мейнстрим язык исходя только из одной точки зрения на проблему.

ARK> Про мутабельность это я провел параллель — если стоять на позиции "мутабельность нужна", то надо равным образом и про анонимные типы говорить.


Я не понимаю твоего черно/белого подхода. Я тебе привел один из примеров где могут очень пригодится мутабельные рекорды. Анонимные типы в этом случае, очевидно, применить нельзя — они годны для сериализации и абсолютно бесполезны для десериализации.
Рекорды прежде всего нацелены на представление всевозможных DTO. И дизайн мутабельных DTO вполне имеет право на жизнь даже если у нас правильный сериализатор, умеющий в конструкторы, и мы не поленились в сотнях классов эти конструкторы завести.
Анонимные типы при этом заточены под представление ad-hoc типов, требующихся при запросе к БД, чтобы не плодить ORM чудовищ, генерящих select *. Для этого применения мутабельность не нужна, потому что эти типы предназначены для типизации туплов по месту их получения, и их принципиально невозможно использовать в качестве DTO.
Поэтому доказательство по аналогии, чем ты упорно занимаешься уже которое сообщение, это на самом деле никакое не доказательство.

ARK>Будет весело, если они в RC2 мутабельность эту уберут.


А если не уберут? Будет грустно?
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[33]: Welcome to C# 9.0
От: artelk  
Дата: 18.09.20 05:41
Оценка: :)
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Здравствуйте, artelk, Вы писали:


A>>Другой вариант: не ставить readonly на backing field.

НС>Ну пипец просто. Ради того чтобы не дать сделать мутабельность надо добавить возможность мутабельности любым свойствам безусловно. Абсурд на марше.
Что не понятно-то? От рефлексии readonly тебя не спасет, а без рефлексии backing field недоступен.
Так что вполне можно было сделать так, что десериализация в иммутабельный рекорд (и класс с init-only свойствами) работала бы без проблем.
Re[36]: Welcome to C# 9.0
От: artelk  
Дата: 18.09.20 06:57
Оценка: +2
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Здравствуйте, AlexRK, Вы писали:


НС>Рекорды прежде всего нацелены на представление всевозможных DTO. И дизайн мутабельных DTO вполне имеет право на жизнь даже если у нас правильный сериализатор, умеющий в конструкторы, и мы не поленились в сотнях классов эти конструкторы завести.

Вот с этим нельзя не согласиться Вручную реализовывать IEquatable, == и т.п. и потом поддерживать их — это проблема актуальна и для мутабельных классов.
Но она актуальна и для структур.
Лучше бы остановились на модификаторе data и разрешили его применять и к классам и к струкурам, чтобы можно было, например, делать "readonly data struct".
А термин record оставили бы на будущее для чего-то более существенного — для именованных туплов с именованными полями. Причем, чтобы выбор о том, использовать под капотом класс или readonly struct для них по дефолту делался компилятором (но можно было и явно задать).
Re[34]: Welcome to C# 9.0
От: Ночной Смотрящий Россия  
Дата: 18.09.20 09:28
Оценка:
Здравствуйте, artelk, Вы писали:

A>Так что вполне можно было сделать так, что десериализация в иммутабельный рекорд (и класс с init-only свойствами) работала бы без проблем.


Нельзя. Я тебе еще раз напомню, что нормальные десериализаторы не через рефлексию работают.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[35]: Welcome to C# 9.0
От: artelk  
Дата: 18.09.20 11:17
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Здравствуйте, artelk, Вы писали:


A>>Так что вполне можно было сделать так, что десериализация в иммутабельный рекорд (и класс с init-only свойствами) работала бы без проблем.


НС>Нельзя. Я тебе еще раз напомню, что нормальные десериализаторы не через рефлексию работают.


А FieldInfo/PropertyInfo они откуда берут? Для кодогеренации они тоже нужны.
Кстати, вот попробовал с SRE:
public delegate void ClassFieldSetter<in T, in TValue>(T target, TValue value) where T : class;

public static class FieldSetterCreator
{
    public static ClassFieldSetter<T, TValue> CreateClassFieldSetter<T, TValue>(FieldInfo field)
        where T : class
    {
        return CreateSetter<T, TValue, ClassFieldSetter<T, TValue>>(field);
    }

    private static TDelegate CreateSetter<T, TValue, TDelegate>(FieldInfo field)
    {
        return (TDelegate)(object)CreateSetter(field, typeof(T), typeof(TValue), typeof(TDelegate));
    }

    private static Delegate CreateSetter(FieldInfo field, Type instanceType, Type valueType, Type delegateType)
    {
        var setter = new DynamicMethod("", typeof(void), new[] { instanceType, valueType }, field.DeclaringType.Module, true);
        var generator = setter.GetILGenerator();
        generator.Emit(OpCodes.Ldarg_0);
        generator.Emit(OpCodes.Ldarg_1);
        generator.Emit(OpCodes.Stfld, field);
        generator.Emit(OpCodes.Ret);
        return setter.CreateDelegate(delegateType);
    }
}

public class Foo
{
    private readonly int x;
    public int X => x;
}

class Program
{
    static void Main()
    {
        var x = typeof(Foo).GetField("x", BindingFlags.Instance | BindingFlags.NonPublic);
        var setX = FieldSetterCreator.CreateClassFieldSetter<Foo, int>(x);
        var foo = new Foo();
        setX(foo, 42);
        Console.WriteLine(foo.X); // 42
    }
}

readonly на поле успешно проигнорировался.
Отредактировано 18.09.2020 12:12 artelk . Предыдущая версия .
Re[34]: Welcome to C# 9.0
От: alexzzzz  
Дата: 18.09.20 16:18
Оценка: +1 :)
Здравствуйте, artelk, Вы писали:

A>Что не понятно-то? От рефлексии readonly тебя не спасет, а без рефлексии backing field недоступен.


Запись в readonly backing field без рефлексии и unsafe:

using System;
using System.Runtime.InteropServices;

internal class Program
{
    [StructLayout(LayoutKind.Explicit)]
    private struct Union
    {
        [FieldOffset(0)] public Foo foo;
        [FieldOffset(0)] public Bar bar;
    }

    private class Foo
    {
        public int Property { get; } = 42;
    }

    private class Bar
    {
        public int field;
    }

    private static void Main()
    {
        var foo = new Foo();
        Console.WriteLine(foo.Property); // 42

        var union = default(Union);
        union.foo = foo;
        union.bar.field = -42;

        Console.WriteLine(foo.Property); // -42
    }
}
Re[35]: Welcome to C# 9.0
От: artelk  
Дата: 18.09.20 20:30
Оценка:
Здравствуйте, alexzzzz, Вы писали:

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


A>>Что не понятно-то? От рефлексии readonly тебя не спасет, а без рефлексии backing field недоступен.

A>Запись в readonly backing field без рефлексии и unsafe:
A>
[StructLayout(LayoutKind.Explicit)]
A>    private struct Union
A>    {
A>        [FieldOffset(0)] public Foo foo;
A>        [FieldOffset(0)] public Bar bar;
A>    }
//...

Ээ.. почитай контекст обсуждения. Я возражал на утверждение о том, что если не ставить readonly на backing field у init-only свойств, то они якобы станут мутабельными.
Ты показал трюк еще более низкоуровневый, чем рефлексия, в котором тебе известно о лэйауте класса Foo.
Это еще один аргумент в пользу того, что readonly на backing field у init-only свойств необязателен? Аргумент не очень.
Или это возражение мне? Ну ок, надо было написать как-то так: "От рефлексии readonly тебя не спасет, а без хотя бы рефлексии backing field недоступен."
Или так: "Backing field напрямую недоступен, чтобы до него добраться нужна как минимум рефлексия, но даже от рефлексии readonly тебя уже не спасет".
Re[36]: Welcome to C# 9.0
От: alexzzzz  
Дата: 20.09.20 19:47
Оценка:
Здравствуйте, artelk, Вы писали:

A>>>Что не понятно-то? От рефлексии readonly тебя не спасет, а без рефлексии backing field недоступен.

A>>Запись в readonly backing field без рефлексии и unsafe:
A>>
[StructLayout(LayoutKind.Explicit)]
A>>    private struct Union
A>>    {
A>>        [FieldOffset(0)] public Foo foo;
A>>        [FieldOffset(0)] public Bar bar;
A>>    }
A>//...
A>

A>Ээ.. почитай контекст обсуждения. Я возражал на утверждение о том, что если не ставить readonly на backing field у init-only свойств, то они якобы станут мутабельными.
A>Ты показал трюк еще более низкоуровневый, чем рефлексия, в котором тебе известно о лэйауте класса Foo.
A>Это еще один аргумент в пользу того, что readonly на backing field у init-only свойств необязателен? Аргумент не очень.

Нет, это просто рефлекторная реакция на «без рефлексии backing field недоступен»
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.