.NET中的“链接”语句是否有任何性能优势?

时间:2008-09-19 20:47:56

标签: .net performance

从表中检索查找代码值时,有些人会这样做......

Dim dtLookupCode As New LookupCodeDataTable()
Dim taLookupCode AS New LookupCodeTableAdapter()
Dim strDescription As String

dtLookupCode = taLookupCode.GetDataByCodeAndValue("EmpStatus", "FULL")
strDescription = dtLookupCode.Item(0).Meaning

...但是,我也看到过这样的事情已经“链接”了......

strDescription = taLookupCode.GetDataByCodeAndValue("EmpStatus", "FULL").Item(0).Meaning

...由于表适配器知道结果集的结构是什么样的,因此首先绕过了查找代码数据表。

使用“chained”方法是否可以节省创建数据表对象的开销,还是有效地创建它以便正确处理.Item(0).Meaning语句?

11 个答案:

答案 0 :(得分:5)

这两行会编译成同样的东西。我会选择哪一个更容易阅读。内联通常指的是a bit different

答案 1 :(得分:4)

从“内联”部分来看,实际上,这两组代码不会编译成同一个东西。问题在于:

Dim dtLookupCode As New LookupCodeDataTable()
Dim taLookupCode AS New LookupCodeTableAdapter()

在VB中,这将使用适当命名的引用创建新对象。其次是:

dtLookupCode = taLookupCode.GetDataByCodeAndValue("EmpStatus", "FULL")

我们立即用新对象替换原始dtLookupCode引用,这会创建要收集的垃圾(RAM中无法访问的对象)。

因此,在确切的原始场景中,所谓的“内联”技术是技术上,性能更高。 (但是,你不太可能在这个小例子中看到这种差异。)

代码基本相同的地方是原始样本如下所示:

Dim taLookupCode AS New LookupCodeTableAdapter
Dim dtLookupCode As LookupCodeDataTable
Dim strDescription As String

dtLookupCode = taLookupCode.GetDataByCodeAndValue("EmpStatus", "FULL")
strDescription = dtLookupCode.Item(0).Meaning

在这个世界中,我们只有现有的引用,而不是创建垃圾对象。为了便于阅读,我对这些陈述进行了重新排序,但要点是相同的。此外,您可以使用类似的内容轻松地对引用进行单行初始化,并具有相同的基本概念:

Dim taLookupCode AS New LookupCodeTableAdapter
Dim dtLookupCode As LookupCodeDataTable = taLookupCode.GetDataByCodeAndValue("EmpStatus", "FULL")
Dim strDescription As String = dtLookupCode.Item(0).Meaning

答案 2 :(得分:2)

是的,不要说“内联”,因为这意味着其他语言中的特定内容。最有可能的是性能差异为零或者小到无关紧要,这只是一个偏好问题。您是想在单独的语句中写出来以使其更清晰,或者将其全部写在一行上以便更快地输入它?

答案 3 :(得分:2)

通常它只会使代码的可读性降低。

通常,当人们使用这种“内联”(即链接)时,他们将多次重新访问类的属性或字段,而不是只获取一次并存储在局部变量中。这通常是一个坏主意,因为通常不知道该字段或属性是如何返回的。例如,它可以每次计算,或者可以计算一次并私下存储在类中。

这是两个插图。第一个片段是要避免的:

if (ConfigurationManager.AppSettings("ConnectionString") == null)
{
    throw new MissingConfigSettingException("ConnectionString");
}

string connectionString = ConfigurationManager.AppSettings("ConnectionString");

第二个是可取的:

string connectionString = ConfigurationManager.AppSettings("ConnectionString")

if (connectionString == null)
{
    throw new MissingConfigSettingException("ConnectionString");
}

这里的问题是AppSettings()实际上必须在每次检索到值时取消装箱AppSettings集合:

// Disassembled AppSettings member of ConfigurationManager 

public static NameValueCollection AppSettings
{
    get
    {
        object section = GetSection("appSettings");

        if ((section == null) || !(section is NameValueCollection))
        {
            throw new
                ConfigurationErrorsException(SR.GetString("Config_appsettings_declaration_invalid"));
        }

        return (NameValueCollection) section;
    }
}

答案 4 :(得分:1)

如果你想看到中间状态,并且单步进入阶段,调试后者会更难。

我会考虑这里使用的屏幕不动产的可读性,因为性能很好。

答案 5 :(得分:1)

我称之为链接。

你问的是错误的问题。

您需要问的是:哪个更具可读性?

如果链接使代码更容易阅读和理解,那么就去做吧。

但是,如果它混淆了,那就不要。

任何性能优化都是不存在的。不要优化代码,优化算法。

所以,如果你打算调用Item(1)和Item(2),那么通过链接,你将一遍又一遍地创建同一个对象,这是一个糟糕的算法。

在这种情况下,第一个选项更好,因为您不需要每次都重新创建适配器。

答案 6 :(得分:1)

反对'链接'的一个原因是Law of Demeter,这表明您的代码在LookupCodeDataTable发生变化时很脆弱。

您应该添加如下函数:

function getMeaning( lookupCode as LookupCodeDataTable)
 getMeaning=lookupCode.Item(0).Meaning
end function

并将其称为:

strDescription=getMeaning(taLookupCode.GetDataByCodeAndValue("EmpStatus", "FULL"))

现在可以在许多其他地方调用getMeaning(),如果LookupCodeDataTable发生变化,那么你只需要更改getMeaning()来修复它。

答案 7 :(得分:0)

结构仍然是创建的,你只是没有它的参考。

答案 8 :(得分:0)

此:

dtLookupCode = taLookupCode.GetDataByCodeAndValue("EmpStatus", "FULL")
strDescription = dtLookupCode.Item(0).Meaning

和此:

strDescription = taLookupCode.GetDataByCodeAndValue("EmpStatus", "FULL").Item(0).Meaning

完全等效。

在第一个示例中,您有一个显式的临时引用(dtLookupTable)。在第二个示例中,临时引用是隐式的。在幕后,编译器几乎肯定会为这两者创建相同的代码。即使没有发出相同的代码,额外的临时引用也非常便宜。

但是,我不确定这一行:

Dim dtLookupCode As New LookupCodeDataTable()

效率很高。在我看来,这会创建一个新的LookupCodeDataTable,然后在后面的语句中覆盖变量时将其丢弃。我不用VB编程,但我希望这行应该是:

Dim dtLookupCode As LookupCodeDataTable

引用很便宜(可能是免费的),但构建额外的查找表可能不是。

答案 9 :(得分:0)

除非您需要通过引用返回的对象,否则它是相同的 taLookupCode.GetDataByCodeAndValue(“EmpStatus”,“FULL”)或项目(0) 多次。否则,你不知道这个函数的运行时是log(n)还是n,所以为了最好的选择,我会为它分配一个引用。

答案 10 :(得分:0)

除了可维护性之外,这是避免链接的另一个原因:错误检查。

是的,您可以将整个事物包装在try / catch中,并捕获链的任何部分可能抛出的每个异常。

但是如果你想在没有try / catch的情况下验证调用之间的结果,你必须将事情分开。例如:

  • 当GetDataByCodeAndValue返回null时会发生什么?
  • 如果它返回一个空列表怎么办?

如果您正在进行链接,则无法在没有try / catch的情况下检查这些值。