当枚举不可为空并且没有任何空选项时,请检查其为空

时间:2019-06-20 16:30:24

标签: c# enums null

这与下面的问题不同

How to tell if an enum property has been set? C#

我正在使用现有的DataContract类创建WCF Rest服务。 我无法将枚举之类的属性数据类型更改为枚举吗?并且也无法在枚举中添加未定义,无选择或默认设置的任何新选项,因为如果我进行这些更改中的任何一项,都会对整个公司产生广泛的影响,并且许多应用程序都将依赖它。

通常,人们使用POSTMAN之类的应用程序调用我的WCF REST服务,他们在其中发送json数据(如下所示),其中Gender是一个包含Male,Female,Transgender等的枚举。 >我想添加验证逻辑,以在QA使用POSTMAN调用我的服务时检查枚举是否为null并发送JSON数据(即使该枚举不可为空,并且枚举中也没有任何None,Null选项?如果为NULL,我想将ArguementNullException发送回带有好消息的调用方。我想优雅地处理这种情况。

public enum Gender 
{
  Male = 0,
  Female = 1,
  Transgender = 2
}

下面很好

{
      "Name" : "XXX"
      "Gender" : "1"
}

以下引发错误

{
      "Name" : "XXX"
      "Gender" : ""
}

解决方案:

感谢p.s.w.g指出正确的方向,我在下面标记了他的答案。我正在使用Newtonsoft,所以我在下面做到了

string stringfydata = Newtonsoft.Json.JsonConvert.SerializeObject(requestGender);
if(string.IsNullOrEmpty(stringfydata))
{
   throw new ArgumentNullException("Gender value cannot be NULL or Empty.");
}

2 个答案:

答案 0 :(得分:2)

除了显而易见的使类中的枚举变形的选项(在您的特定情况下可能不起作用)外,您可以将enum变量设置为超出枚举范围的整数。之后,您可以检查是否在枚举中定义了整数。 从C#does not check enumerations开始,您可以执行以下操作:

    public enum Gender
    {
        Male = 0,
        Female = 1,
        Transgender = 2
    }

    public int HandleGender(string strJsonGender){
        if (strJsonGender == "")
        {
            return -1;
        }
        else {
            // Get int representation of the gender
            return (int)((Gender)Enum
                    .Parse(typeof(Gender),
                           strJsonGender, true));
        }
    }

    public void MainMethod(string strJsonGender) {
        Gender gVal;
        int iVal = HandleGender(strJsonGender);

        if (Enum.IsDefined(typeof(Gender), iVal))
        {
            // Handle if the an actual gender was specified
            gVal = (Gender)iVal;
        }
        else { 
            // Handle "null" logic
        }

答案 1 :(得分:1)

注意:由于您已在问题中指出,下面的答案使用DataContracts,但Json.Net serialization也有类似的解决方案。

您可以使用[DataMember(EmitDefaultValue = false)]来忽略根本没有指定Gender的情况。在这种情况下,返回的值将是为枚举成员分配了值0的值(请注意,如果没有成员具有该值,您仍然会得到值0,该值可能是对您有用)。

[DataContract]
class Person
{
    [DataMember]
    public string Name { get; set; }

    [DataMember(EmitDefaultValue = false)]
    public Gender Gender { get; set; }
}


void Main()
{
    var json = "{\"Name\": \"XXX\"}";
    var ser = new DataContractJsonSerializer(typeof(Person));
    var obj = ser.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json)));
    obj.Dump(); // Person { Name = "XXX", Gender = Male }
}

要处理提供的空字符串而不是有效值或根本没有值的情况,您可以使用以下技巧:

[DataContract]
class Person
{
    [DataMember]
    public string Name { get; set; }

    [IgnoreDataMember]
    public Gender Gender
    {
        get
        {
            if (GenderValue.GetType() == typeof(string))
            {
                Enum.TryParse((string)GenderValue, out Gender result);
                return result;
            }
            return (Gender)Convert.ToInt32(GenderValue);
        }
        set
        {
            GenderValue = value;
        }
    }

    [DataMember(Name = "Gender", EmitDefaultValue = false)]
    private object GenderValue { get; set; }
}


void Main()
{
    var json = "{\"Name\": \"XXX\", \"Gender\": \"\"}";
    var ser = new DataContractJsonSerializer(typeof(Person));
    var obj = ser.ReadObject(new MemoryStream(Encoding.UTF8.GetBytes(json)));
    obj.Dump(); // Person { Name = "XXX", Gender = Male }
}

但是,这有点尴尬,很容易被滥用。我建议您谨慎使用此方法。正如其他人提到的,我们通常希望在将无效值提供给函数/ API时引发错误。通过'failing fast',您可以让尝试使用API​​的用户知道他们已经构建了一个可能在某个时候产生意外结果的请求。