我认为必须是一个常见的问题。假设我有一个典型的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参数时会抛出异常。不确定发生了什么。我不知道现在是否可以重现这些错误。
答案 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>
,文章的其余部分很有趣,但不在您的问题范围内: - )