Ответы пользователя по тегу Структуры данных
  • Как понять что в объект была добавлена информация, но не изменена существующая?

    Casper-SC
    @Casper-SC
    Программист (.NET)
    Если нужно бросать исключение (я бы бросал). С массивами ты ничего не сделаешь, чтобы нельзя было менять часть массива. Нужно использовать свой тип данных вместо массива, в котором и делать проверки.
    using System;
    
    namespace ConsoleApp1
    {
        public class ModelBase
        {
            protected bool CheckValueTypeField<T>(T field)
                where T : struct
            {
                return field.Equals(default(T));
            }
    
            protected bool CheckReferenceTypeField<T>(T field)
                where T : class
            {
                return field == null;
            }
    
            protected void ThrowIfNotDefault<T>(T field)
                where T : struct
            {
                if (!CheckValueTypeField(field))
                {
                    throw new InvalidOperationException();
                }
            }
    
            protected void ThrowIfNotNull<T>(T field)
                where T : class
            {
                if (!CheckReferenceTypeField(field))
                {
                    throw new InvalidOperationException();
                }
            }
        }
    
        public class TestModel : ModelBase
        {
            private string _name;
            private int _value;
    
            public string Name
            {
                get { return _name; }
                set
                {
                    ThrowIfNotNull(_name);
                    _name = value;
                }
            }
    
            public int Value
            {
                get { return _value; }
                set
                {
                    ThrowIfNotDefault(_value);
                    _value = value;
                }
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                var test = new TestModel();
                test.Name = "test name";
                test.Value = 1;
    
                try
                {
                    test.Name = "new name";
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
    
                try
                {
                    test.Value = 5;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
    
                Display(test);
            }
    
            static void Display(TestModel model)
            {
                Console.WriteLine(
                    $"{nameof(model.Name)} == {model.Name}; {nameof(model.Value)} == {model.Value};");
            }
        }
    }


    Можно, конечно, и так, но игнорировать изменения и никого об этом не уведомлять так себе затея.
    public class TestModel : ModelBase
        {
            private string _name;
            private int _value;
    
            public string Name
            {
                get { return _name; }
                set
                {
                    if (!CheckReferenceTypeField(_name))
                    {
                        _name = value;
                    }
                }
            }
    
            public int Value
            {
                get { return _value; }
                set
                {
                    if (!CheckValueTypeField(_value))
                    {
                        _value = value;
                    }
                }
            }
        }


    Или такой вариант, пока не определился с поведением, как определишься, можно удалить параметр из конструктора и часть поведения.
    using System;
    
    namespace ConsoleApp1
    {
        public abstract class ModelBase
        {
            private readonly bool _throwAnExceptionInsteadOfAnEvent;
    
            public event EventHandler FieldIsNotDefault;
    
            protected ModelBase(bool throwAnExceptionInsteadOfAnEvent = true)
            {
                _throwAnExceptionInsteadOfAnEvent = throwAnExceptionInsteadOfAnEvent;
            }
    
            protected bool CheckValueTypeField<T>(T field)
                where T : struct
            {
                return field.Equals(default(T));
            }
    
            protected bool CheckReferenceTypeField<T>(T field)
                where T : class
            {
                return field == null;
            }
    
            protected void AssertIsNotDefault<T>(T field)
                where T : struct
            {
                if (!CheckValueTypeField(field))
                {
                    if (_throwAnExceptionInsteadOfAnEvent)
                    {
                        throw new InvalidOperationException();
                    }
    
                    OnFieldIsNotDefault();
                }
            }
    
            protected void AssertIsNotNull<T>(T field)
                where T : class
            {
                if (!CheckReferenceTypeField(field))
                {
                    if (_throwAnExceptionInsteadOfAnEvent)
                    {
                        throw new InvalidOperationException();
                    }
    
                    OnFieldIsNotDefault();
                }
            }
    
            protected void OnFieldIsNotDefault()
            {
                FieldIsNotDefault?.Invoke(this, EventArgs.Empty);
            }
        }
    
        public class TestModel : ModelBase
        {
            private string _name;
            private int _value;
    
            public string Name
            {
                get { return _name; }
                set
                {
                    AssertIsNotNull(_name);
                    _name = value;
    
                }
            }
    
            public int Value
            {
                get { return _value; }
                set
                {
                    AssertIsNotDefault(_value);
                    _value = value;
                }
            }
    
            public TestModel()
                : base(false)
            {
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                var test = new TestModel();
                test.FieldIsNotDefault += OnFieldIsNotDefault;
                test.Name = "test name";
                test.Value = 1;
    
                try
                {
                    test.Name = "new name";
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
    
                try
                {
                    test.Value = 5;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
    
                test.FieldIsNotDefault -= OnFieldIsNotDefault;
                Display(test);
            }
    
            private static void OnFieldIsNotDefault(object sender, EventArgs e)
            {
                Console.WriteLine("Поле уже установлено");
            }
    
            static void Display(TestModel model)
            {
                Console.WriteLine(
                    $"{nameof(model.Name)} == {model.Name}; {nameof(model.Value)} == {model.Value};");
            }
        }
    }
    Ответ написан
    Комментировать