繁体   English   中英

使用整数设置枚举属性并验证参数

[英]Set an enum property using an integer & validate the argument

编辑:我已经改变了问题的标题,包括对论证的验证,更清楚我要问的是什么。

我试图在C#中创建一个类,它有一个用int设置的属性并返回一个枚举,这可能是基本的,但我是一个C#noob。

使用int参数的设置是一个特殊的限制,我不会进入,并且是在Vbscript中设置COM的东西。

我正在寻找创建这些RSSCalendarDay对象,以便它们可以放在一个列表中,每个对象从周日到周六(1到7)都有一个唯一的RSSCalendarRuleDay。

它是使用xCal和本地数据来制作重复事件的真正基本方法的一部分。

到目前为止,我的代码在下面,你可以看到get&set是不完整的,我坚持参数的验证(首先检查它是一个int,等等),这就是我之前尝试使用dayOrderValue的东西,以及我所有的可以在线找到的是使用int.Parse和int.TryParse,但是它们用于解析字符串,而不是我想做的事情。

public class RSSCalendarDay {

    private RSSCalendarRuleDay? _dayOrder;
    /// <summary>
    /// Passed an Integer from 1 to 7 to represent the particular day of the week as an enum
    /// </summary>
    public RSSCalendarRuleDay? DayOrder {
        get {
                       // TODO
        } 
        set {
            if (value != null) {
                int dayOrderValue;
                if () {
                    throw new ArgumentException("Invalid day order specified");
                }
                if(dayOrderValue < 1 || dayOrderValue > 7) {
                    throw new ArgumentException("Invalid day type specified (out of day range of 1 to 7)");
                }
                _dayOrder = (RSSCalendarRuleDay) dayOrderValue;
            }
            else {
                _dayOrder = null;
            }
        } 
    }
    public DateTime? TimeOpens { get; set; }
    public DateTime? TimeCloses { get; set; }

    /// <summary>
    /// These are the relevant BYDAY abbreviations used in the xCal recurring rule specification
    /// to represent what days a recurring event is open in a comma separated list
    /// </summary>
    public enum RSSCalendarRuleDay {
        SU=1,MO=2,TU=3,WE=4,TH=5,FR=6,SA=7
    }
}

你可以像这样将int转换为Enum

RSSCalendarRuleDay foo = Enum.ToObject(typeof(RSSCalendarRuleDay) , intValue);

或者简单地投下它

RSSCalendarRuleDay foo = (RSSCalendarRuleDay) intValue;

请注意,由于您使用的是setter,因此setter会期望Enum值,而不是整数,因此您需要使用setter 之前将其强制转换。

请注意,即使未为Enum定义值,ToObject也将始终成功。 如果要进行边界检查,可以使用Enum.IsDefined方法

var exists = Enum.IsDefined(typeof(RSSCalendarRuleDay) , intValue);

您无法定义“使用int设置并返回枚举”的属性。 根据设计,属性的getter和setter声明为相同类型。

但是,您可以做的是定义两个属性,它们都访问相同的支持字段,一个作为枚举,另一个转换为int:

public class RSSCalendarDay
{
    private RSSCalendarRuleDay? dayOrder;

    public RSSCalendarRuleDay? DayOrder
    {
        get { return this.dayOrder; }
        set { this.dayOrder = value; }
    }

    public int DayOrderInt
    {
        get { return this.dayOrder.HasValue ? (int)this.dayOrder: 0; }
        set { this.dayOrder = value != 0 ? (RSSCalendarRuleDay?)value : null; }
    }
}

在上面的代码中,如果指定int值为0(反之亦然),我已经简化了逻辑以将后备字段设置为null; 这可能不是你想要的。

因此,以下两个分配将具有相同的效果:

RSSCalendarDay cd1 = new RSSCalendarDay();
cd1.DayOrder = RSSCalendarRuleDay.TH;

RSSCalendarDay cd2 = new RSSCalendarDay();
cd2.DayOrderInt = 5;

编辑 :如果要执行参数验证,可以使用类似的方法:

public class RSSCalendarDay
{
    private RSSCalendarRuleDay dayOrder;

    public RSSCalendarRuleDay DayOrder
    {
        get { return this.dayOrder; }
        set { this.dayOrder = value; }
    }

    public int DayOrderInt
    {
        get 
        { 
            return (int)this.dayOrder;
        }
        set
        {
            if (!Enum.IsDefined(typeof(RSSCalendarRuleDay), value))
                throw new ArgumentException("Invalid day value specified (out of day range of 1 to 7).");
            this.dayOrder = (RSSCalendarRuleDay)value; 
        }
    }
}

Enum.IsDefined检查枚举是否包含指定的值。 在您的情况下,条件等于value < 1 || value > 7 value < 1 || value > 7

请注意,在上面的代码中, DayOrder不可为空, 0被视为无效的日期值。

编辑2 :重新设置默认值:我个人的偏好是将枚举的 0 成员定义为未知; 继续你的双字母约定,我将其命名为NA (“不可用”)。

public enum RSSCalendarRuleDay {
    NA=0,SU=1,MO=2,TU=3,WE=4,TH=5,FR=6,SA=7
}

这很方便,因为在初始化RSSCalendarDay实例而没有显式设置其dayOrder字段时,它会自动默认为RSSCalendarRuleDay.NA 我上面给出的第二个片段也会随着这种改变而改变,因为Enum.IsDefined现在会接受0-7(而不是1-7)的范围。

不要使代码过于复杂:枚举在内部由数字表示(默认为int ),因此可以从int转换为enum值(反之亦然)。

所以这就是你如何做到的:

public RSSCalendarRuleDay DayOrder { get; set; }

...

RSSCalendarDay xx = new RSSCalendarDay(...)
xx.DayOrder = (DayOrder)4;  // Will set WE for the DayOrder property

...

// If you need to get the value as an int
int dayOrderAsInt = (int)xx.DayOrder;

// Still possible to affect invalid values however
RSSCalendarRuleDay z = (RSSCalendarRuleDay)8;

// So if you want to check for int validity:
if (Enum.IsDefined(typeof(RSSCalendarRuleDay), dayOrderAsInt))
{
    // If we're here, the value is valid !
}

另外,确保你真的需要DayOrder可以为空(如果不是这样,请删除?)。

问题是,由于您将其声明为Enum ,因此您无法在属性的setter中收到与Enum不同的任何内容。 一种替代方案可能是这样的:

private int? dayOrderInt;

public int? DayOrderInt
{
     get { return dayOrderInt; }
     set { if (value < 1 || value > 7) throw new ArgumentException(string.Format("{0} is an invalid day of the week", value)); dayOrderInt = value; }
}

public RSSCalendarRuleDay? DayOrder
{
    get { if (DayOrderInt.HasValue) return (RSSCalendarRuleDay)DayOrderInt; return null; }
}

以下对我有用:

RSSCalendarRuleDay Example = (RSSCalendarRuleDay)1; 

我不认为这是可以实现的。 您将属性类型设置为RSSCalendarRuleDay? 当你想将az整数传递给它时,编译器将抛出一个错误。 顺便说一句,这种方法非常混乱(比如当你打算返回一个IEnumerable但有时你会返回null)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM