2012-02-07 43 views
2

编辑:我已经改变了问题的标题,包括验证的参数,要更清楚我所问。使用整数和验证参数设置枚举属性

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

通过使用int参数进行的设置是一个特殊的限制,我不会介绍它,它是通过Vbscript在COM上设置的。

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

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

到目前为止我的代码是下面,你可以看到得到&集是不完整的,我被困在变元的验证(检查它的一个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 
    } 
} 

回答

3

您无法定义“使用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

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

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

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

这是方便,因为,当你没有明确设置其dayOrder场初始化RSSCalendarDay情况下,它会自动默认为RSSCalendarRuleDay.NA。我上面给出的第二个片段也可以在此更改中保持不变,因为Enum.IsDefined现在可以接受0-7(而不是1-7)的范围。

+0

好的回答:)我觉得这个“价值!= 0”也很重要,但很微妙,我会用你的建议来代替。谢谢 – Pricey 2012-02-07 20:38:59

+0

而是,我的意思是“而不是我现有的代码”。 – Pricey 2012-02-07 20:53:04

+0

我现在认为第二个片段可能更接近你所需要的。第一个片段仅仅将'null'替换为'0'。 – Douglas 2012-02-07 21:12:33

3

你可以一个int转换为枚举像这样

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

或者简单地浇铸

RSSCalendarRuleDay foo = (RSSCalendarRuleDay) intValue; 

,因为你使用的是二传手,二传手会做注意期望一个Enum值,而不是一个整数,所以你需要在使用setter之前在之前投射它

请注意,ToObject将始终成功,即使未为Enum定义值。如果你想做一个范围检查,你可以使用Enum.IsDefined方法

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

对不起,我是不是我的问题明确的名字,我铸造的int枚举已经在二传手,但首先我想确认该arg是一个int ,从你的答案我开始认为我不需要..我应该只是尝试以上并抛出相关异常?出于兴趣,Enum.ToObject如何对不在枚举值范围内的intValue作出反应? – Pricey 2012-02-07 20:28:36

+1

转换仍然会成功。如果要显式检查是否为Enum定义了int值,则可以使用'IsDefined'方法。我会将其添加到我的答案中以便说清楚。 – 2012-02-07 20:46:14

+0

感谢有关“IsDefined”的信息。 + 1给你的回答,+1给你的评论。再次感谢。 – Pricey 2012-02-07 20:49:21

0

对我下面的工作:

RSSCalendarRuleDay Example = (RSSCalendarRuleDay)1; 
0

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

+0

您是否说IEnumerable时出现枚举?如果参数为null,我将该属性设置为null,但我忘记了在类实例化时将_dayOrder设置为null。但是,当参数为null时,我没有看到使用枚举值设置属性的理由。 – Pricey 2012-02-07 20:46:49

1

不要你的代码过于复杂:枚举由数字(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为可以为空(如果不是的话,去掉?)。

+0

+1好答案。说实话,我不确定它是否需要为空。我认为如果我不设置它默认会是0?但我的枚举范围是特定的1至7?此外,因为他们代表了一周的几天,我不想设置默认的一天..仍然不确定这一天。 – Pricey 2012-02-07 21:07:05

1

问题在于,自从您声明为Enum以来,您无法在设置者中接收与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; } 
} 
+0

+1。也是一个很好的答案,并验证从1到7的范围。 – Pricey 2012-02-07 20:40:37