假设我有三个类A,B和C,它们以我可以通过A(即A.B.C)访问C到C的方式嵌套。如果我正在尝试访问C的简单属性,比如Id类型int,并且我没有在A中实现B的新实例(或B中的C),我会得到一个'对象引用未设置为实例一个东西。'错误。
我想知道的是,如果有一种简单的方式可以告诉我A.B.C.Id,如果你不能因为某些东西是空的,那么就给我一个默认值。
var myId = A.B.C.Id <some operator> -1;
目前我正在做这样的事情而且感觉太可怕了。
var myId = A == null ? -1 : A.B == null ? -1 : A.B.C == null ? -1 : A.B.C.Id;
答案 0 :(得分:4)
通过A或B引用C或两者都打破了Law of Demeter,这是不好的做法。如果需要引用某些东西,那么就会有一个空的构造函数来构建那种连接。
答案 1 :(得分:2)
在C#中没有特殊的语法可以做你想做的事。
但是有一些建筑方法,如何做到这一点。
您可以使用Null Object Design Pattern 或者您可以使用允许null的扩展方法扩展A,B,C类:
var myId = A.BOrNull().COrNull().IdOrNull();
public class A {
public B B { get; set; }
}
public static class AExtensionMethods {
public static B BOrNull( this A a ) {
return null != a ? a.B : null;
}
}
public class B {
public C C { get; set; }
}
public static class BExtensionMethods {
public static C COrNull( this B b ) {
return null != b ? b.C : null;
}
}
public class C {
public int Id { get; set; }
}
public static class CExtensionMethods {
public static int? IdOrNull( this C c ) {
return null != c ? (int?)c.Id : null;
}
}
答案 2 :(得分:1)
查看dependency injection,当你创建一个新的A实例时,它将在A中创建C和A中的B.或者只是将代码放在类的构造函数中创建这样的实例。 (所以在A()中创建B,在B()中创建C
感觉错误的原因是,正如其他人所指出的那样,你不应该处于可能发生这种情况的情况。
答案 3 :(得分:1)
如果你必须深入研究,你可能想在A中创建一个属性,给你null或B.C.Id.
答案 4 :(得分:1)
这非常适合Null Object设计模式。
基本上,像这样定义NullB:
public class NullB : B
{
public override C C
{
get { return new NullC(); }
}
}
然后定义NullC:
public class NullC : C
{
public override int Id
{
get { return 0; }
}
}
这显然要求所讨论的类具有虚拟成员,但这样更安全。然后,当你有B和C的真实实例时,你只需使用并返回它们。
答案 5 :(得分:0)
您可以使用属性检查请求的类是否为null。如果是,它将创建该类的新实例。
class ClassA
{
private ClassB m_ClassB = null;
public ClassB B
{
get
{
//check if we already have an instance of the class.
//if not create it
if (m_ClassB == null)
{
m_ClassB = new ClassB();
}
return m_ClassB;
}
}
}
class ClassB
{
private ClassC m_ClassC = null;
public ClassC C
{
get
{
//check if we already have an instance of the class.
//if not create it
if (m_ClassC == null)
{
m_ClassC = new ClassC();
}
return m_ClassC;
}
}
}
class ClassC
{
private int m_Id = 123;
public int ID
{
get
{
return m_Id;
}
}
}
然后你可以像这样访问你需要的东西
CLassA A = new ClassA();
int id = A.B.C.ID;
答案 6 :(得分:-2)
您可以尝试以下代码:
var myId = -1;
try
{
myId = A.B.C.Id;
}
catch (NullReferenceException e)
{
myId = -1;
}