V
V
Vasily2019-05-28 18:18:44
Algorithms
Vasily, 2019-05-28 18:18:44

How to understand that information has been added to the object, but the existing one has not been changed?

Good day.
Tell me, is there any simple way to understand that information has been added to the object but the existing one has not been changed?
There is a Customer object, it has various fields Name, Age, Addresses[], Jobs[]
The task is to allow adding new data to the object, but prohibit changing existing ones, for example:

class Customer {
  public int Id { get; set; }
  public string Name { get; set; }
  public int Age { get; set; }
  public Address[] Addresses { get; set; }
  public Job[] Jobs { get; set; }


  public void ChangeCustomer() {
    if (Name != null) {
      Name = "Новое имя"; // <- так нельзя
    }

    if (Age == null) {
      Age = 20; // <- так можно
    }
  }
}

The whole thing is complicated by the fact that my customer model contains more than two dozen fields, some of which are arrays.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
R
Ronald McDonald, 2019-05-28
@Zoominger

Well, describe this logic in set, for example, that's why it was invented.

P
Planet_93, 2019-05-28
@Planet_93

Example

public class Customer
    {
        private string name;
        private int age;
        public int Id { get; set; }
        public string Name
        {
            set
            {
                if (name != null)
                {
                    Console.WriteLine("Поле уже заполнено " + name);
                }
                else
                {
                    name = value;
                }
            }
            get { return name; }         
        }
        public int Age
        {
            get { return age; }
            set
            {
                if (age != 0)
                {
                    Console.WriteLine("Поле уже заполнено " + age);
                }
                else
                {
                    age = value;
                }
            }
        }
        public Address[] Addresses { get; set; }
        public Job[] Jobs { get; set; }

    }

B
Boris the Animal, 2019-07-20
@Casper-SC

If you need to throw an exception (I would throw). With arrays, you can't do anything to make it impossible to change part of the array. You need to use your data type instead of an array, in which to do checks.

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};");
        }
    }
}

It is possible, of course, and so, but ignoring the changes and not notifying anyone about this is a so-so idea.
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;
                }
            }
        }
    }

Or such an option, until you decide on the behavior, as you decide, you can remove the parameter from the constructor and part of the behavior.
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};");
        }
    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question