Здравствуйте, 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>
Если не важна производительность и типобезопасность, то можно подобное сделать через рефлексию, например:
Основная проблема заключается в том, что для решения данной задачи без рефлексии, нужно иметь возможность получить делегат на setter формируемый свойством, а такой возможности нет.
Здравствуйте, 4058, Вы писали:
4>Здравствуйте, vaa, Вы писали:
4>Основная проблема заключается в том, что для решения данной задачи без рефлексии, нужно иметь возможность получить делегат на setter формируемый свойством, а такой возможности нет.
Да, это ужасно на самом деле.
Я бы предпочел модифицировать код при помощи макроса или АОП, чем обмазываться ифчиками. жиза
Здравствуйте, 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"));
}
}
Здравствуйте, 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; }
}
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, 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);
IMHO все "автоматизированные" решения плохи, ибо они требую наличия и самое главное поддержки метаданных на уровне типа, определяющих то, какие поля могу быть обнулены, какие — нет. Это может диктоваться как типом данных ссылочный/валью, так и соображениями бизнес логики.
Кто то в полях делегаты хранит, кто то родительские объекты всякие обзерверы и так далее — при обнулении которых сами понимаете что будет.
Со временем понадобятся исключения из правил и так далее. в плане изучения/саморазвития самое то. В общем случае ключевое слово ref в прокладном коде — является кодсмелзом.
Я бы просто сделал метод Reset() и следил бы по возможности, чтобы в него никто не пытался передавать параметры
Здравствуйте, 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);
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, 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));
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, 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;
}
}
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, vaa, Вы писали: vaa>Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?
Забавно, что обратная задача (заменить null на "") имеет готовое решение, встроенное в язык:
a.Name ??= string.Empty;
И это работает для локальных переменных, полей, и свойств.
Если у вас такого много, то безумное решение становится не таким уж и безумным. Можно напилить библиотеку string transformations, которая построена на перегрузке операторов. Использовать "<<" не выйдет, но оператор & не намного хуже.
И тогда можно делать всякие компактные вещи типа
a.Name &= NullIfEmpty & ToProperCase;
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, vaa, Вы писали:
vaa>Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?
Почему бы не сделать поле, а свойство над ним не сгенерить сорс-генератором? Пример оттуда для реализации INotifyPropertyChanged:
using PropertyChanged.SourceGenerator;
public partial class MyViewModel
{
[Notify] private string _lastName;
public string FullName => $"Dr. {LastName}";
}
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Почему бы не сделать поле, а свойство над ним не сгенерить сорс-генератором?
И как это всё поможет решить исходную задачу? Или ты предлагаешь поле сделать публичным?
Тогда непонятно, нафига вообще свойство.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, vaa, Вы писали:
vaa>>Возможно ли что-то похожее для св-в чтобы сократить кол-во ифчиков?
VD>Почему бы не сделать поле, а свойство над ним не сгенерить сорс-генератором? Пример оттуда для реализации INotifyPropertyChanged: VD>
Здравствуйте, Sinclair, Вы писали:
S>И как это всё поможет решить исходную задачу? Или ты предлагаешь поле сделать публичным? S>Тогда непонятно, нафига вообще свойство.
Поля передаются по ссылке. Делаешь универсальный метод в классе и дело в шляпе.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.