Обнулить свойство
От: vaa  
Дата: 28.04.23 02:12
Оценка:
SetNull принимает поля, но не св-ва или индексаторы.
Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?

class A
{
 public string Name {get;set;}
}
void SetNull(ref string v) => if (v == "") v = null;
SetNull(ref a.Name);
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re: Обнулить свойство
От: 4058  
Дата: 28.04.23 04:25
Оценка:
Здравствуйте, vaa, Вы писали:

vaa>SetNull принимает поля, но не св-ва или индексаторы.

vaa>Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?

vaa>
vaa>class A
vaa>{
vaa> public string Name {get;set;}
vaa>}
vaa>void SetNull(ref string v) => if (v == "") v = null;
vaa>SetNull(ref a.Name);
vaa>


Если не важна производительность и типобезопасность, то можно подобное сделать через рефлексию, например:

void SetNullProperty(string input, object target, string propertyName)
{
    if (input == string.Empty) SetPropertyValue(null, target, propertyName);
}

void SetPropertyValue(object input, object target, string propertyName)
{
    target.GetType().GetProperty(propertyName).SetValue(target, input);
}

SetNullProperty("", a, "Name");


Основная проблема заключается в том, что для решения данной задачи без рефлексии, нужно иметь возможность получить делегат на setter формируемый свойством, а такой возможности нет.
Re[2]: Обнулить свойство
От: vaa  
Дата: 28.04.23 04:42
Оценка:
Здравствуйте, 4058, Вы писали:

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



4>Основная проблема заключается в том, что для решения данной задачи без рефлексии, нужно иметь возможность получить делегат на setter формируемый свойством, а такой возможности нет.

Да, это ужасно на самом деле.
Я бы предпочел модифицировать код при помощи макроса или АОП, чем обмазываться ифчиками. жиза
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re: Обнулить свойство
От: kov_serg Россия  
Дата: 28.04.23 09:19
Оценка:
Здравствуйте, vaa, Вы писали:

vaa>SetNull принимает поля, но не св-ва или индексаторы.

vaa>Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?

vaa>
vaa>class A
vaa>{
vaa> public string Name {get;set;}
vaa>}
vaa>void SetNull(ref string v) => if (v == "") v = null;
vaa>SetNull(ref a.Name);
vaa>


using System;

class A {
    public string Name { get; set; }
}

public class Ref<T> {
    public Func<T> get { get; private set; }
    public Action<T> set { get; private set; }
    Ref(Func<T> get, Action<T> set) { this.get = get; this.set = set; }
    public static Ref<T> propery<Y>(Y y, string name, params object[] index) {
        var p = typeof(Y).GetProperty(name);
        return new Ref<T>( () => (T)p.GetValue(y, index), v => p.SetValue(y, v, index) );
    }
}

class App {
    static void SetNull(ref string v) { if (v == "") v = null; }
    static void SetNull(Ref<string> v) { if (v.get() == "") v.set(null); }

    static void Main(string[] args) {
        string Name = "";
        var a = new A() { Name = "" };

        SetNull(ref Name);
        SetNull(Ref<string>.propery(a, "Name"));
    }
}
Отредактировано 28.04.2023 9:32 kov_serg . Предыдущая версия .
Re: Обнулить свойство
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.04.23 11:04
Оценка: 4 (1) +2 :)
Здравствуйте, vaa, Вы писали:

vaa>SetNull принимает поля, но не св-ва или индексаторы.

vaa>Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?

using System;
using System.Linq.Expressions;
using System.Reflection;

public class Program
{
    public static void Main()
    {
        var a = new A() { Name = "" };
        SetNull(() => a.Name);
        
    }
    public static void SetNull(Expression<Func<string>> getExpr)
    {
        var v = getExpr.Compile()();
        if (v == "")
        {
            if (getExpr.Body is MemberExpression me)
            {
                var target = Expression.Lambda(me.Expression).Compile().DynamicInvoke();
                if (me.Member is FieldInfo fi)
                    fi.SetValue(target, null);
                else if (me.Member is PropertyInfo pi)
                    pi.SetValue(target, null);
            }
        }
    }
}

public class A
{
    public string Name { get; set; }
}
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Обнулить свойство
От: kov_serg Россия  
Дата: 28.04.23 11:35
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>        SetNull(() => a.Name);

Слегка нарушает принцип наименьшего удивления. Передаёшь get-тер, но неожиданно получаешь изменение данных.
Re: Обнулить свойство
От: rameel https://github.com/rsdn/CodeJam
Дата: 28.04.23 11:55
Оценка:
Здравствуйте, vaa, Вы писали:

vaa>SetNull принимает поля, но не св-ва или индексаторы.

vaa>Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?

Почему нельзя вот так?

var a = new A();
SetNull(v => a.Name = v, value);

void SetNull(Action<string?> action, string? value) =>
    action(value != "" : value : null);


Если не хочется плодить замыкания, то можно так

var a = new A();
SetNull((o, v) => o.Name = v, a, "");

void SetNull<T>(Action<T, string?> action, T obj, string? value) =>
    action(obj, value == "" ? null : value);
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re: Обнулить свойство
От: 尿컙拋㕪⬎⤇Ǥ꧃푙刾ꄔ൒  
Дата: 28.04.23 12:02
Оценка:
IMHO все "автоматизированные" решения плохи, ибо они требую наличия и самое главное поддержки метаданных на уровне типа, определяющих то, какие поля могу быть обнулены, какие — нет. Это может диктоваться как типом данных ссылочный/валью, так и соображениями бизнес логики.
Кто то в полях делегаты хранит, кто то родительские объекты всякие обзерверы и так далее — при обнулении которых сами понимаете что будет.

Со временем понадобятся исключения из правил и так далее. в плане изучения/саморазвития самое то. В общем случае ключевое слово ref в прокладном коде — является кодсмелзом.

Я бы просто сделал метод Reset() и следил бы по возможности, чтобы в него никто не пытался передавать параметры
Re: Обнулить свойство
От: IT Россия linq2db.com
Дата: 28.04.23 13:55
Оценка: 84 (2) +3
Здравствуйте, vaa, Вы писали:

vaa>SetNull принимает поля, но не св-ва или индексаторы.

vaa>Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?

vaa>
vaa>class A
vaa>{
vaa> public string Name {get;set;}
vaa>}
vaa>void SetNull(ref string v) => if (v == "") v = null;
vaa>SetNull(ref a.Name);
vaa>


A так? Зато без всякой рефлексии.

class A
{
    public string Name {get;set;}
}
void NullIfEmpty(string v) => v { Length : 0 } ? null : v;
a.Name = NullIfEmpty(a.Name);
Если нам не помогут, то мы тоже никого не пощадим.
Re[3]: Обнулить свойство
От: Sinclair Россия https://github.com/evilguest/
Дата: 28.04.23 14:59
Оценка: 9 (1)
Здравствуйте, kov_serg, Вы писали:
_>Слегка нарушает принцип наименьшего удивления. Передаёшь get-тер, но неожиданно получаешь изменение данных.
Ну название метода кагбэ намекает на его функциональность. Можно и вашим способом, но тогда бы я сделал так:
public class Ref
{
    public static Ref<T> Property<T, Y>(Y obj, T property, [CallerArgumentExpression("property")] string? propPath = null)
    {
        var propDotPos = propPath.LastIndexOf('.') + 1;
        var propName = propPath.Substring(propDotPos);
        var p = typeof(Y).GetProperty(propName);
        return new Ref<T>(() => (T)p.GetValue(obj), v => p.SetValue(obj, v));
    }
}
public class Ref<T>
{
    public Func<T> get { get; private set; }
    public Action<T> set { get; private set; }
    public Ref(Func<T> get, Action<T> set) { this.get = get; this.set = set; }
}

С вот таким использованием:
        var a = new A() { Name = "" };
        SetNull(Ref.Property(a, a.Name));
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Обнулить свойство
От: vaa  
Дата: 28.04.23 23:15
Оценка:
Здравствуйте, IT, Вы писали:


IT>A так? Зато без всякой рефлексии.


IT>
IT>class A
IT>{
IT>    public string Name {get;set;}
IT>}
IT>void NullIfEmpty(string v) => v { Length : 0 } ? null : v;
IT>a.Name = NullIfEmpty(a.Name);
IT>


будет лишнее присваивание. но суть не в этом, хочется максимально сократить кол-во кода.
макросом бы это в лет решилось.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[3]: Обнулить свойство
От: Doc Россия http://andrey.moveax.ru
Дата: 29.04.23 08:25
Оценка: +3
Здравствуйте, vaa, Вы писали:

vaa>будет лишнее присваивание.


На фоне альтернативы в виде рефлексии это замечание выглядит странно
Re: Обнулить свойство
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.04.23 16:42
Оценка: 13 (2) +1 :)
Здравствуйте, vaa, Вы писали:
vaa>Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?
Продолжаем двигаться по пути безумия:
using static Weird;
public class Program
{
    public static void Main()
    {
        var a = new A() { Name = "" };
        a.Name &= NullIfEmpty; // <--- !
    }
}

public class A
{
    public string Name { get; set; }
}
public abstract class Weird
{
    public abstract string? Apply(string? value);
    public static string? operator &(string str, Weird a) => a.Apply(str);
    public static readonly Weird NullIfEmpty = new Replace("", null);
    private class Replace : Weird
    {
        private string? _replace;
        private string? _by;
        public Replace(string? replace, string? by) => (_replace, _by) = (replace, by);
        public override string? Apply(string? value) => value == _replace ? _by : value;
    }
}
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Обнулить свойство
От: Sinclair Россия https://github.com/evilguest/
Дата: 29.04.23 16:43
Оценка: +2
Здравствуйте, IT, Вы писали:
Тут есть риск промахнуться при копи-пейсте:
a.FirstName = NullIfEmpty(a.LastName);
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Обнулить свойство
От: Sinclair Россия https://github.com/evilguest/
Дата: 02.05.23 09:28
Оценка: 21 (2)
Здравствуйте, vaa, Вы писали:
vaa>Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?
Забавно, что обратная задача (заменить null на "") имеет готовое решение, встроенное в язык:
a.Name ??= string.Empty;

И это работает для локальных переменных, полей, и свойств.

Если у вас такого много, то безумное решение становится не таким уж и безумным. Можно напилить библиотеку string transformations, которая построена на перегрузке операторов. Использовать "<<" не выйдет, но оператор & не намного хуже.
И тогда можно делать всякие компактные вещи типа
a.Name &= NullIfEmpty & ToProperCase;
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Обнулить свойство
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.05.23 23:59
Оценка:
Здравствуйте, vaa, Вы писали:

vaa>Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?


Почему бы не сделать поле, а свойство над ним не сгенерить сорс-генератором? Пример оттуда для реализации INotifyPropertyChanged:
using PropertyChanged.SourceGenerator;

public partial class MyViewModel
{
    [Notify] private string _lastName;
    public string FullName => $"Dr. {LastName}";
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Обнулить свойство
От: Sinclair Россия https://github.com/evilguest/
Дата: 04.05.23 05:45
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Почему бы не сделать поле, а свойство над ним не сгенерить сорс-генератором?

И как это всё поможет решить исходную задачу? Или ты предлагаешь поле сделать публичным?
Тогда непонятно, нафига вообще свойство.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[2]: Обнулить свойство
От: vaa  
Дата: 04.05.23 11:23
Оценка:
Здравствуйте, VladD2, Вы писали:

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


vaa>>Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?


VD>Почему бы не сделать поле, а свойство над ним не сгенерить сорс-генератором? Пример оттуда для реализации INotifyPropertyChanged:

VD>
VD>using PropertyChanged.SourceGenerator;

VD>public partial class MyViewModel
VD>{
VD>    [Notify] private string _lastName;
VD>    public string FullName => $"Dr. {LastName}";
VD>}
VD>

модель из xsd. уже реализует INotifyPropertyChanged
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[3]: Обнулить свойство
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.05.23 12:36
Оценка:
Здравствуйте, vaa, Вы писали:

vaa>модель из xsd. уже реализует INotifyPropertyChanged


Да не важно. Я в качестве примера привел.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Обнулить свойство
От: VladD2 Российская Империя www.nemerle.org
Дата: 04.05.23 12:38
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>И как это всё поможет решить исходную задачу? Или ты предлагаешь поле сделать публичным?

S>Тогда непонятно, нафига вообще свойство.

Поля передаются по ссылке. Делаешь универсальный метод в классе и дело в шляпе.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.