阅读this Eric Lippert文章后,我了解如果我们将本地变量保持未初始化,C#编译器不会喜欢它。
当我遇到这个'问题'我不时地查看了一些旧代码,并且能够清除大部分实际上不需要未初始化(SomeClass obj = null
)局部变量的情况。
但我想出了一个我不知道如何重构代码的情况。
public void DoSomething(string foo) {
SomeClass obj; // = null;
try {
obj = SomeClass.CreateItem(target);
} catch(CustomException ex) {
// notify UI of error
}
if (obj != null) {
// do something with `obj`
}
}
由于外部因素, SomeClass.CreateItem
可能会失败。如果是,我想通知用户,如果不是,我想要执行操作。
C#编译器不希望我将obj
保持未初始化状态,因此我通常为其分配null
。
这感觉像是一个' hack'现在,我的问题是:
上面的代码中是否存在设计缺陷?
如果有的话,我应该如何在编译时处理引用,何时我无法确定它们是否会在运行时指向现有对象?
答案 0 :(得分:9)
我会像这样重构代码:
private SomeClass TryToCreateItem()
{
try
{
return SomeClass.CreateItem(target);
}
catch(CustomException ex)
{
// notify UI of error
}
return null;
}
public void DoSomething(string foo)
{
SomeClass obj = TryToCreateItem();
if (obj != null) {
// do something with `obj`
}
"提取方法"是我最喜欢的重构。
答案 1 :(得分:2)
// do something with
obj``代码应位于try
块`内。
您尝试执行的操作是运行一些可能成功或可能不成功的代码,然后仅在前一代码成功时运行其他代码。这通常是一个非常强烈的信号,即其他代码是同一逻辑块的一部分,依赖于没有异常。如果构造此对象有异常,则需要跳过此代码,这正是将其包含在try
块中所获得的行为。
答案 2 :(得分:0)
您可以重构它以将所有代码封装在与该对象相关的try / catch中,如果确实确实需要做某些事情,如果它失败那么你可以使用bool将它与你的其余代码:
public void DoSomething(string foo)
{
bool failedCreation = false;
try
{
SomeClass obj = SomeClass.CreateItem(target);
}
catch (CustomException ex)
{
// notify UI of error
failedCreation = true;
}
if (failedCreation)
{
// do other stuff.
}
}
但这看起来并不像你想到的那样。我将封装try / catch中的所有内容并完成它。