2011-09-26 229 views
2

我有我认为必须是一个共同的问题。可以说我有一个典型的Person类,我有一个汽车类,它有一个类型的人的场/业主:C#设置属性/字段值为none

public class Car 
{ 
    Person owner;   
} 

但有时我想要的车有没有所有者。处理这个问题的建议方法是什么? (可编辑:澄清,我的意思是你不能使用Person?owner;)

我可以添加一个布尔字段/属性:hasOwner,但这似乎相当冗长,所以我觉得像这样的人创造类人型的静态成员没有的:

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(); 
    } 
} 
} 

编译并运行了,虽然会有一个问题,如果你想继承表格的人类,与通用和非通用versons。更多有经验的c#程序员的想法将不胜感激。

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

Edit2:我想我得到的异常时,我传递null参数。不知道发生了什么事。我不知道现在是否可以重现错误。

+3

为什么设置'Person'变量'null'不一个选项? – Oded

+0

同意,可以请你解释一句“空类型不起作用引用类型已经为空。” –

+0

@正好。为什么重新发明轮子? –

回答

1

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

+0

问题在于您无法将null作为方法/构造函数参数传递。 null表示没有设置值,这是不同的形式值是none。 –

+2

@Rich Olvier“你不能将null作为一个方法/构造函数参数” - 当然可以的。 –

+0

没有硬性规定'null'表示'未设定值'。最终,'null'的意思是任何你想要的。 如果确实需要分清“值不设置”和“无”,那么你有几种选择 - 例如一个特殊的“空对象”,就像你在上面做的那样,一个持有者结构相当于'Nullable '或者像组件模型的'XyzSpecified'这样的边车属性。所有这些都有优点和缺点,选择取决于您的预期用途。 –

1

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

+0

对于可为空的类型,我认为监视器值没有多大意义。 – Oded

1

确实,为什么没有空值适合解决我们的问题。如果所有者为空,则意味着所有者根本不存在...

0

第一种解决方案是在设计模式中称为空对象的东西。 通常情况下,它会做一些不同的事情,您将创建一个从Person继承的新类。

public class Person 
{ 
    public int age; 
} 

public class NoPerson : Person 
{ 
} 

然后你可以用typeof()声明

+0

也许有人不喜欢它......我认为这是一个有效的方法,如果你想强制非空值,无论是理由(我想有人可以带着理由为什么不能有空)。更糟糕的是,这可能是静态类(因为只有一个“nobody”:)),您甚至可以拥有表示该情况的数据库对象(即-1)的硬编码ID。 –

+0

你仍然会遇到来自Person的继承问题,不是我顺便投了票。 –

0

是的,静态属性/领域是有点怪,当你有继承验证此。一个框架的例子是EventArgs.Empty字段,国际海事组织将很高兴有更多的专业类。

如果你期望继承Person,并且你希望在整个继承类中强制实现“这个人就是没有人”,那么我的建议就是你将这个概念添加到类本身。

如果你作出这样的返回true或false一个人是否是“没有人”还是不虚方法,派生类可用来扩展此检查,以满足他们各自的类别的需求:

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:

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

你当然可以结合上面的静态字段上的班,所以对您个人类,你就会有一个

public static readonly Person Nobody = new Person(); 

和派生类(注意使用new改性剂这里)

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

我从来没有见过这种方法(与'新'修改器)在野外,并会个人是相当不愿意使用它,但如果它在您的域是有意义的,它可能是一个替代看看。

0

给予含义null是一种有效的方法,但一般来说,我发现它确实最好有这种情况的“富裕”的支持。

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

例如,看this article from Bart De Smet(寻找Option<T>,在本文的其余部分是有趣的,但不是你的问题:-)范围)