C#将属性/字段的值设置为无
我认为这是一个常见的问题。假设我有一个典型的Person类和一个Car类,其中字段/属性所有者的类型为Person:C#将属性/字段的值设置为无,c#,C#,我认为这是一个常见的问题。假设我有一个典型的Person类和一个Car类,其中字段/属性所有者的类型为Person: public class Car { Person owner; } 但有时我希望车没有主人。处理这个问题的推荐方法是什么。可为空的类型不起作用,因为引用类型已经可以为空。(编辑:澄清,我的意思是您不能使用Person?owner;) 我可以添加一个bool字段/属性:hasOwner,但这似乎相当冗长,因此我考虑在Person类中创建一个静态成员,类型
public class Car
{
Person owner;
}
但有时我希望车没有主人。处理这个问题的推荐方法是什么。可为空的类型不起作用,因为引用类型已经可以为空。(编辑:澄清,我的意思是您不能使用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();
}
}
}
这是编译和运行的,尽管我还没有在实际应用程序中使用它。然后我想我可以创建一个包含none成员的泛型类:
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();
}
}
}
命名空间控制台应用程序2
{
公共类非成员,其中T:new()
{
公共静态T无;
静态非成员()
{
无=新的T();
}
}
公共类人员:非成员
{
}
公车
{
公众人物所有者;
}
班级计划
{
静态void Main(字符串[]参数)
{
汽车报废=新车();
.owner=Person.none;
如果(dumped.owner==Person.none)
控制台。写(“这辆车没有主人”);
Console.ReadLine();
}
}
}
它编译并运行,但如果您想继承person类的形式,使用泛型和非泛型的韵文,则会出现问题。经验丰富的c#程序员的想法将不胜感激
编辑:使用null表示none的问题是不能将null作为方法/构造函数参数传递。null表示未设置值,与value is none不同
Edit2:当我传递空参数时,我以为我会抛出异常。不知道发生了什么事。我不知道现在是否可以重现错误。这两种方法都是有效的。您可能会发现,大多数应用程序只是将属性保留为
null
,并使用一个特殊值来指示空值通常用于值类型(TimeSpan.Min
等)。我通常将其保留原样,如果车主为null,这意味着它没有车主。如果有值,则无需复杂化—它有所有者,否则它没有(系统已知的)所有者。
此策略的例外情况是,当您需要日志数据库时,但在这种情况下,您通常可以拥有版本化的汽车和车主,并使用相同的原则。的确,为什么不使用空值来解决我们的问题呢。如果owner为null,则表示owner根本不存在…第一个解决方案是在设计模式中称为null对象的东西。 通常情况下,它的实现略有不同,您创建了一个从Person继承的新类
public class Person
{
public int age;
}
public class NoPerson : Person
{
}
然后您可以使用
typeof()
语句验证这一点是的,当您继承时,静态属性/字段有点奇怪。一个框架示例是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
}
被覆盖的人员
的一个简单示例可以是定义为“无人”的员工,如果基类(人员)说是,或者如果没有设置员工编号:
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();
对于派生类(注意这里修饰符的用法)
我从未在野外见过这种方法(使用“新”修饰符),我个人会非常不愿意使用它,但如果它在你的领域有意义,它可能是一种替代方法。赋予
空值的意义是一种有效的方法,但总的来说,我觉得在这种情况下获得“更丰富”的支持确实更可取
您始终可以为引用类型构建自己的“可空类型”。您将没有编译器支持(例如,没有人?
),但您可以获得非常接近的东西
例如,查看(查找选项
,文章的其余部分很有趣,但不在您的问题范围内:-)为什么将Person
变量设置为null
不是选项?同意,请您解释一下“可空类型不起作用,因为引用类型已经可以空了。”@完全正确。为什么要重新发明轮子?@Morawski-dunno。如果你重新发明它,你可以从一开始就对它进行镀铬?我的意思是,Person-owner=null有什么问题代码>?可为null的类型只是让您拥有一个null值类型。对于可为null的类型,我认为监视器值没有什么意义。问题是您不能将null作为方法/构造函数参数传递。null表示未设置值,与value is none不同。@Rich Olvier“您不能将null作为方法/构造函数参数传递”-当然可以。没有硬性规定null
表示“未设置值”。最后,null
表示您希望它的意思。如果您确实需要区分“未设置值”和“无”,那么您有几个选项-例如,如上所述的特殊“空对象”,相当于Nullable
的holder结构,或组件模型XyzSpecified
的侧车属性。它们都有优点和缺点,选择取决于您的预期用途。@Morawski是的,您是对的。我不确定发生了什么,我以为当我传递null时会抛出异常。因此我的任务。可能有人不喜欢它。。。我认为这是一个有效的方法,如果你
new public static readonly Employee Nobody = new Employee();