C#将property / field设置为none值

时间:2011-09-26 09:11:11

标签: c#

我认为必须是一个常见的问题。假设我有一个典型的Person Class,我有一个Car Class,它有一个Person类型的字段/属性所有者:

public class Car
{
    Person owner;        
}

但有时候我希望这辆车没有车主。什么是处理这个问题的推荐方法。 Nullable类型不起作用,因为引用类型已经可以为空。(编辑:澄清,我的意思是你不能使用Person?owner;)

我可以添加一个bool字段/属性:hasOwner,但这看起来相当冗长,所以我想在Person类中创建一个静态成员Person,如下所示:

namespace ConsoleApplication2
{
public class Person
{
    public static Person none;
    public int age;

    static Person()
    {
        none = new Person();
    }
}

public class Car
{
    public Person owner;
}

class Program
{
    static void Main(string[] args)
    {
        Car dumped = new Car();
        dumped.owner = Person.none;
        Console.ReadLine();
    }
}
}

这个编译并运行,虽然我没有在实际应用程序中使用它。然后我想我可以创建一个没有成员的泛型类:

namespace ConsoleApplication2
{
public class NoneMember<T> where T : new()
{
    public static T none;

    static NoneMember ()
    {
        none = new T();
    }
}

public class Person: NoneMember<Person>
{        
}

public class Car
{
    public Person owner;
}

class Program
{
    static void Main(string[] args)
    {
        Car dumped = new Car();
        dumped.owner = Person.none;
        if (dumped.owner == Person.none)
            Console.Write("This car has no owner");
        Console.ReadLine();
    }
}
}

编译并运行,尽管如果你想继承形式的人类,使用通用和非通用的版本会有问题。更有经验的c#程序员的想法将不胜感激。

编辑:使用null表示none的问题是您不能将null作为方法/构造函数参数传递。 null表示未设置的值,与value不同。

Edit2:我认为在传递null参数时会抛出异常。不确定发生了什么。我不知道现在是否可以重现这些错误。

6 个答案:

答案 0 :(得分:1)

两者都是有效的方法。您可能会发现大多数应用程序只是将属性保留为null并且具有特殊值以指示空值通常用于值类型(TimeSpan.Min等)。

答案 1 :(得分:1)

我通常会保持原样,如果Car的所有者为null,那就意味着 - 它没有所有者。没有必要复杂化,如果有价值 - 它有所有者,否则它没有(系统已知)所有者。 当您需要具有日记数据库时,此策略的例外情况就是这种情况,但在这种情况下,您通常可以使用版本化的汽车和所有者并使用相同的原则。

答案 2 :(得分:1)

的确,为什么不使用null值来解决我们的问题。如果owner为null,则表示所有者根本不存在...

答案 3 :(得分:0)

第一个解决方案是在设计模式中调用的一个空对象。 通常它会有一些不同,你创建一个继承自Person的新类。

public class Person
{
    public int age;
}

public class NoPerson :  Person
{
}

然后,您可以使用typeof()语句

对此进行验证

答案 4 :(得分:0)

是的,当你有继承时,静态属性/字段有点奇怪。一个框架示例是EventArgs.Empty字段,IMO可以在更专业的类上使用。

如果您期望从Person继承,并且您希望在继承的类中强制执行“此人无人”,那么我建议您将此概念添加到类本身。

如果你创建一个返回true或false的虚方法,无论一个人是否为“nobody”,你的派生类可以扩展这个检查以满足他们各自类的需要:

public class Person
{
    public Person()
    {
        // This constructor will create a "nobody"
    }

    public Person(string name)
    {
        // Proper initialization
        this.Name = name;
        _isNobody = false;
    }

    public string Name { get; set; }

    public virtual bool IsNobody
    {
        get 
        {
            return String.IsNullOrEmpty(this.Name) == false;
        }
    }

    // TODO: Maybe override Equals/==/GetHashCode to take IsNobody into account
}

重写Person的一个简单示例可能是一个Employee,如果基类(Person)表示它或者未设置员工编号,则定义为“Nobody”:

public class Employee : Person
{      
    public int EmployeeNumber { get; set; }
    public override bool IsNobody
    {
        return base.IsNobody || EmployeeNumber == -1;
    }
}

你当然可以将上面的内容与你的类上的静态字段结合起来,所以在你的Person类中你有一个

public static readonly Person Nobody = new Person();

和派生类(注意在这里使用new修饰符)

new public static readonly Employee Nobody = new Employee();

我从未见过这种做法(使用'新'修饰符)并且 个人 非常不愿意使用但如果它在您的域中有意义,则可能是另一种选择。

答案 5 :(得分:0)

null赋予意义是一种有效的方法,但一般来说,我发现确实更喜欢对这种情况有“更丰富”的支持。

您始终可以为引用类型构建自己的“可空类型”。你不会有编译器支持(例如没有Person?),但是你可以获得非常接近的东西。

例如,查看this article from Bart De Smet(查找Option<T>,文章的其余部分很有趣,但不在您的问题范围内: - )