C#枚举类型与可空属性名冲突问题

4
以下是与枚举和属性命名冲突相关的问题:这个这个 以及 这个

我的问题不是关于命名规范的,而是想知道如何解决以下代码中的名称冲突:
namespace Test
{
    public class Person
    {
        // 1)
        // Gender? Gender { get; set; }

        // 2)
        Gender Gender { get; set; }

        public Person ()
        {
            // 1 - Error CS1061: Type `Test.Gender?' does not contain a definition for `Male' and no extension method `Male' of type `Test.Gender?' could be found (are you missing a using directive or an assembly reference?) (CS1061) (Test)
            // 2 - OK
            Gender = Gender.Male;
        }
    }

    public enum Gender
    {
        Male = 1,
        Female
    }
}

如果我将属性声明为2中的形式Gender Gender { get; set; },代码编译成功,然而,如果我将其声明为1中的形式Gender? Gender { get; set; }(在上面的代码中有注释),则会出现错误。

Error CS1061: Type `Test.Gender?' does not contain a definition for `Male' and no extension method `Male' of type `Test.Gender?' could be found (are you missing a using directive or an assembly reference?) (CS1061) (Test)

为什么会发生这种情况呢?
2个回答

7
Gender?代表Nullable<Gender>,这意味着当您编写Gender.Male时,编译器认为您正在尝试调用Nullable<Gender>实例上名为Male的属性的getter方法,即Gender被解释为读取this.Gender属性,而Male被解释为读取该属性结果中名为Male的属性。
由于枚举不能有方法,因此编译器不会将情况(2)识别为错误,因为唯一合理的解决方法是将符号作为枚举本身。
您可以通过增加名称限定来解决此问题:
namespace Acme.Fruits.Banana
{
    ...
    public Person()
    {
        Gender = Banana.Gender.Male
    }
    ...
}

@Bobson:我已经编辑过了,展示了如何修复这个问题。请根据你正在使用的命名空间进行调整。 - Paul Ruane

2

属性或本地变量优先于类型/枚举,这意味着如果一个变量或属性与类型/枚举同名,则编译器将解析标识符的任何使用为变量/属性。

public class Test
{
     public static void SomeMethod(){}
}

public static void Main()
{
     Test.SomeMethod();//ERROR... cannot use variable before declaring it.
     object Test = new object();
     Test.SomeMethod();//ERROR... object does not have a method SomeMethod
}

唯一的例外情况是如果属性/变量与其自身类型同名,则编译器允许其访问静态成员。
public class Test
{
     public static void SomeMethod(){}
}

public static void Main()
{         
     Test Test = new Test();
     Test.SomeMethod();//Works
}

然而,可空类型并不等同于其封装的类型,它的名称采用Nullable<T>的形式,两者之间只有隐式转换,因此在可空类型的情况下,编译器将不再允许访问枚举成员或静态属性。
public struct Test
{
     public static void SomeMethod(){}
}

public static void Main()
{         
     Test? Test = new Test();
     Test.SomeMethod();//ERROR... Test does not have method SomeMethod
}

类似地,变量的声明必须是已经输入的类型,因为编译器需要知道它,例如以下方式将不起作用:

public class Test
{
     public static void SomeMethod(){}
}

public static void Main()
{         
     object Test = new Test();
     Test.SomeMethod();////ERROR... object does not have a instance method SomeMethod
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接