开发者

Validating properties in c#

开发者 https://www.devze.com 2023-02-10 00:57 出处:网络
let\'s suggest I got an interface and inherit class from it, internal interface IPersonInfo { String FirstName { get; set; }

let's suggest I got an interface and inherit class from it,

internal interface IPersonInfo
{
    String FirstName { get; set; }
    String LastName { get; set; }
}
internal interface IRecruitmentInfo
{
    DateTime RecruitmentDate { get; set; }
}

public abstract class Collaborator : IPerso开发者_StackOverflow社区nInfo, IRecruitmentInfo
{
    public DateTime RecruitmentDate
    {
        get;
        set;
    }
    public String FirstName
    {
        get;
        set;
    }
    public String LastName
    {
        get;
        set;
    }
    public abstract Decimal Salary
    {
        get;
    }
}

then how do I validate strings in collaborator class? Is it possible to implement inside properties?


Yes, but not using auto-properties. You will need to manually implement the properties with a backing field:

private string firstName;

public String FirstName
{
    get
    {
        return firstName;
    }
    set
    {
        // validate the input
        if (string.IsNullOrEmpty(value))
        {
            // throw exception, or do whatever
        }
        firstName = value;
    }
}


Something like this...

private string _firstName;
public string FirstName
{
    get
    {
        return _firstName;
    }
    set
    {
        if (value != "Bob")
          throw new ArgumentException("Only Bobs are allowed here!");
        _firstName = value;
    }
}

Basically, what you're using for properties are the syntactic sugar version. At compile time they create a private member variable and wire up the property to use that variable, as I'm doing manually here. The exact reason for this is so that if you want to add logic you can convert it into a manual one like I have here without breaking the implementation of the interface.


Or use DataAnnotations

http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.aspx


Should also mention validation frameworks if you're getting a bit more sophisticated. They can make validation rules much easier to manage, and will also surface errors to your UI, whilst keeping the rules tied to your models so you don't have to have any repetitive boilerplate validation code. Depending on your framework version, one option is DataAnnotations.


As far as I know, if you use the automatic properties syntax, you lose the ability to access the backing fields. According to the documentation (http://msdn.microsoft.com/en-us/library/bb384054.aspx):

In C# 3.0 and later, auto-implemented properties make property-declaration more concise when no additional logic is required in the property accessors. They also enable client code to create objects. When you declare a property as shown in the following example, the compiler creates a private, anonymous backing field that can only be accessed through the property's get and set accessors.

Attributes are permitted on auto-implemented properties but obviously not on the backing fields since those are not accessible from your source code. If you must use an attribute on the backing field of a property, just create a regular property.

So your only solution is to create regular properties.


Yes. You can create a private backing field for the property, like this:

private String _firstName;

public String FirstName
{
     get
     {
          return _firstName;
     }
     set
     {
          //Check value for correctness here:
          _firstName = value;
     }
}


private DateTime recruitmentDate;    
public DateTime RecruitmentDate
{
    get { return recruitmentDate; }
    set
    {
        validate(value);
        recruitmentDate = value;
    }
}


If you mean can you perform custom logic during the get/set of a property in C#, the answer is yes.

Your using what are called Automatic Properties where the backing store and logic is defaulted for you.

You just need to provide it yourself like

private int backingStoreVariable;
public property MyProperty
{
    get
    {
        return this.backingStoreVariable;
    }
    set
    {
        this.backingStoreVariable=value;
    }
}

Now you can run custom validation code in your get and set blocks.


Alternatively, you could not use value types for your fields. For instance, you could create a "FirstName" class with the following implementation:

public class FirstName
{
    private string _Value;
    public string Value
    {
        get
        {
            return _Value;
        }
        set
        {
            if (string.IsNullOrEmpty(value))
                throw new ArgumentNullException("Value cannot be null");
            if (value.Length > 128)
                throw new ArgumentOutOfRangeException("Value cannot be longer than 128 characters");
            _Value  = value;
        }
    }

    public FirstName(string initialValue)
    {
        Value   = initialValue; //does validation check even in constructor
    }
}

Finally, in your code sample above you would simply have:

public interface IPersonInfo
{
    FirstName FirstName { get; set; }
    String LastName { get; set; }
}

and so on with your other properties. Then to use the property in your codel, you would have:

public FirstName MyFirstName;
var x = MyFirstName.Value;

If you have a lot of fields that you want to validate, this might end up being a cumbersome approach. However, you could generalize it to handle certain types of numbers - like positive numbers (ints > 0), or counts (int >= 0), measures, etc.

Strings are harder because they often have length restrictions in addition to value types (such as no special characters, no digits, etc. This might be possible to accomodate by having a read-only length property that is set in the constructor of the inheriting class.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号