在我使用的前一个团队中,每当创建一个新的Service类来处理数据层和表示层之间的业务逻辑时,就会完成以下操作:
class DocumentService
{
public DocumentRepository DocumentRepository { get; set; }
public DocumentService()
{
if (DocumentRepository == null) DocumentRepository = new DocumentRepository();
}
}
我从未完全理解为什么null
的检查存在。如果正在调用构造函数,那意味着它必须为null ..因为它是一个新实例,对吧?
为什么要这样做?在我看来,这似乎是一个多余的步骤,但我不想错过任何东西并将其作为不好的做法传递下去。
答案 0 :(得分:17)
在这个确切的背景下:是的,这是多余的。
此代码没有直接的原因,它可能是旧方法的遗留问题或预期具有多个构造函数的实现。但我不建议使用这个'模式',甚至不保留这些代码。
答案 1 :(得分:12)
亨克的回答当然是正确的;我只是想补充一点,我怀疑它来自何处。我敢打赌,在过去的某个时候有人写道:
class DocumentService
{
private DocumentRespository documentRespository = null;
public DocumentRepository DocumentRepository
{
get
{
if (documentRepository == null)
documentRepository = new DocumentRepository();
return documentRepository;
}
}
public DocumentService()
{
}
}
也就是说,该属性在首次使用时初始化 。后来有人意识到这是错误的或不必要的,或者其他什么,并重写代码将构造放在构造函数中,使属性“渴望”而不是“懒惰”,但忘记取出空检查。
如果人们通过从现有代码剪切和粘贴到新代码进行编程,则该模式可以传播。很快,一个神话就出现了,这就是它必须要做的事情。这就是为什么,我怀疑,如此多的Visual Basic程序员都错误地认为,当你完成Foo时,你必须说Set Foo = Nothing
;在某些情况下,这是必要的,现在人们即使在没有必要的情况下也会这样做,因为这就是我们在这里做的事情。
顺便说一句,你可能想说:
public DocumentRepository DocumentRepository { get; private set; } // note the private
您似乎不太可能希望您的服务用户能够动态更改存储库。
答案 2 :(得分:5)
据我所知,你是绝对正确的。无需检查null
。
答案 3 :(得分:5)
可能会覆盖DocumentRepository的==运算符。
答案 4 :(得分:1)
有一个场景,我可以想到这几乎有意义 - 但你必须在一个C#不是唯一语言的环境中工作(或者你正在进行奇怪的后编译步骤,比如Postsharp可能是可能的。
在C#或VB.Net中,您无法控制何时调用基类构造函数,并且没有语法允许您在调用基类构造函数之前设置基类成员 - 但是没有什么可以阻止它在IL。
如果您在这样的环境中工作,并且您显示的构造函数实际上对DocumentRepository
做了更多的事情,那么您可能正在为以下类正确设置:
public class IllegalCSharpClass : DocumentService
{
public IllegalCSharpClass()
{
DocumentRepository = new DocumentRepository("B");
base(); //This is illegal C#, but allowed in IL
}
}
我不想在这样的工作场所工作。
以下是该课程的IL:
.class public auto ansi beforefieldinit PlayAreaCS_Con.IllegalCSharpClass
extends PlayAreaCS_Con.DocumentService
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
.maxstack 8
IL_0008: ldarg.0
IL_0009: ldstr "B"
IL_000e: newobj instance void PlayAreaCS_Con.DocumentRepository::.ctor(string)
IL_0013: call instance void PlayAreaCS_Con.DocumentService::set_DocumentRepository(class PlayAreaCS_Con.DocumentRepository)
IL_0018: nop
IL_0019: nop
IL_0000: ldarg.0
IL_0001: call instance void PlayAreaCS_Con.DocumentService::.ctor()
IL_0006: nop
IL_0007: nop
IL_001a: ret
}
}