How to make sure a class is valid before referencing?

北战南征 提交于 2020-01-24 09:25:30

问题


    public class Person
    {
        public string FullName { get; set; }
        public int? PhoneNumber { get; set; }
        public int? CarQTY { get; set; }
    }

I want to throw an exception if someone doesn't have the object completely populated. For example, if fullName, phoneNumber, or carQTY is null, I want to throw an exception on the get method.

Do I really have to do this?

    public class Person
    {
        string _FullName;
        int? _PhoneNumber;
        int? _CarQTY;

        private Boolean IsValid()
        {
            Boolean condition = true;
            condition = (FullName != null) && (PhoneNumber != null) && (CarQTY != null);
            return condition;
        }
        public string FullName
        {
            get
            {
                if (!IsValid()) throw new System.ArgumentException("Parameter cannot be null", "fullName is null");
                return _FullName;
            }
            set
            {
                _FullName = value;
            }
        }
        public int? PhoneNumber
        {
            get
            {
                if (!IsValid()) throw new System.ArgumentException("Parameter cannot be null", "phoneNumber is null");
                return _PhoneNumber;
            }
            set
            {
                _PhoneNumber = value;
            }
        }
        public int? CarQTY
        {
            get
            {
                if (!IsValid()) throw new System.ArgumentException("Parameter cannot be null", "carQTY is null");
                return _CarQTY;
            }
            set
            {
                _CarQTY = value;
            }
        }
    }

回答1:


As suggested in the comments, forcing to create the object through a constructor is simply the most efficient way:

    public class Person
    {
        public string FullName { get; private set; }
        public int PhoneNumber { get; private set; }
        public int CarQTY { get; private set; }

        public Person(string fullName, int phone, int carQty){
            FullName = fullName;
            PhoneNumber = phone;
            CarQTY = carQty;
        }
    }

The setters might also be public, if you want to allow the modification of the object once it has been created.




回答2:


Well, this could be a controversial issue in terms of where and how an object should be validated. Should an object complains if it's not created as it should? Or should the creator be responsible for checking the integrity of the object is about to create?

I can digest let me say the second should.

You want to create me, then create me correctly!

Thus, I'd like to suggest the following:

public class Person
{
    public string FullName { get; set; }
    //I suggest the PhoneNumber should be a string type.
    public string PhoneNumber { get; set; }
    public int CarQTY { get; set; }

    public Person() { }

    public Person(string fullName, string phoneNumber, int carQTY) : this()
    {
        FullName = fullName;
        PhoneNumber = phoneNumber;
        CarQTY = carQTY;
    }

    public static Person Parse(string fullName, string phoneNumber, int carQTy)
    {
        if (!TryParse(fullName, phoneNumber, carQTy, out Person person))
            throw new ArgumentException("Incorrect Arguments");

        return person;
    }

    public static bool TryParse(string fullName, string phoneNumber, int carQTy, out Person person)
    {
        person = null;

        if (!string.IsNullOrEmpty(fullName) &&
            !string.IsNullOrEmpty(phoneNumber) &&
            carQTy > 0)
            person = new Person(fullName, phoneNumber, carQTy);

        return person == null ? false : true;
    }

    public override string ToString() =>
        return $"{FullName}, {PhoneNumber}, {CarQTY}";
}

Now, you have two new static functions (Parse, TryParse) the caller can use to create a valid objects. So you can do:

public class SomeClass
{
    private void CreatePerson()
    {
        if(!Person.TryParse(fullName, phoneNumber, carQty, out Person person))
        {
            MessageBox.Show("Invalide Args");
            return;
        }

        //You have a valid person object...
    }
}

Or

public class SomeClass
{
    private void CreatePerson()
    {
        Person person;
        try
        {
            person = Person.Parse(fullName, phoneNumber, carQty);
            //You have a valid person object...
        }
        catch (ArgumentException ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}


来源:https://stackoverflow.com/questions/59567899/how-to-make-sure-a-class-is-valid-before-referencing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!