.NET中的“鏈接”語句是否有任何性能優勢?

[英]Is there any performance benefit with “chaining” statements in .NET?


When retrieving a lookup code value from a table, some folks do this...

從表中檢索查找代碼值時,有些人會這樣做......

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

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

...however, I've also seen things done "chained" like this...

...但是,我也看到過這樣的事情“鏈式”......

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

...which bypasses having a lookup code data table in the first place since the table adapter knows what the structure of its result set looks like.

...由於表適配器知道其結果集的結構是什么樣的,因此首先繞過了查找代碼數據表。

Does using the "chained" method save the overhead of creating the data table object, or does it effectively get created anyway in order to properly handle the .Item(0).Meaning statement?

使用“鏈式”方法是否可以節省創建數據表對象的開銷,還是有效地創建它以便正確處理.Item(0).Meaning語句?

11 个解决方案

#1


4  

Straying from the "inline" part of this, actually, the two sets of code won't compile out to the same thing. The issue comes in with:

實際上,從“內聯”部分來看,這兩組代碼不會編譯成同一個東西。問題在於:

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

In VB, this will create new objects with the appropriately-named references. Followed by:

在VB中,這將使用適當命名的引用創建新對象。其次是:

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

We immediately replace the original dtLookupCode reference with a new object, which creates garbage to be collected (an unreachable object in RAM).

我們立即用新對象替換原始的dtLookupCode引用,這會創建要收集的垃圾(RAM中無法訪問的對象)。

In the exact, original scenario, therefore, what's referred to as the "inline" technique is, technically, more performant. (However, you're unlikely to physically see that difference in this small an example.)

因此,在確切的原始場景中,所謂的“內聯”技術在技術上更具性能。 (但是,你不太可能在這個小例子中看到這種差異。)

The place where the code would essentially be the same is if the original sample read as follows:

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

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

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

In this world, we only have the existing references, and are not creating junk objects. I reordered the statements slightly for readability, but the gist is the same. Also, you could easily single-line-initialize the references with something like this, and have the same basic idea:

在這個世界中,我們只有現有的引用,而不是創建垃圾對象。為了便於閱讀,我對這些陳述進行了重新排序,但要點是相同的。此外,您可以使用類似的東西輕松地對引用進行單行初始化,並具有相同的基本思想:

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

#2


5  

Those two lines would compile down to the same thing. I would pick whichever one is easier for you read. Inlining normally refers to something a bit different.

這兩行將編譯成同樣的東西。我會選擇哪一個更容易閱讀。內聯通常指的是有點不同的東西。

#3


2  

Yeah, don't say "inline" because that means something specific in other languages. Most likely the performance difference is either zero or so small it doesn't matter, it's just a matter of preference. Do you want to write it out in separate statements to make it more clear, or write it all on one line to type it out quicker?

是的,不要說“內聯”,因為這意味着其他語言中的特定內容。最有可能的是,性能差異為零或者小到無關緊要,這只是一個偏好問題。您是否希望在單獨的語句中將其寫出來以使其更清晰,或者將其全部寫在一行以更快地輸入?

#4


2  

Usually it just makes the code less readable.

通常它只會使代碼的可讀性降低。

And often, when people use this "inlining" (i.e. chaining), they'll re-access a property or field of a class multiple times instead of getting it just once and storing in a local variable. This is generally a bad idea because one doesn't usually know how that field or property is returned. For example, it may be calculated each time, or it may be calculated once and stored privately in the class.

通常,當人們使用這種“內聯”(即鏈接)時,他們將多次重新訪問類的屬性或字段,而不是只獲取一次並存儲在局部變量中。這通常是一個壞主意,因為通常不知道該字段或屬性是如何返回的。例如,它可以每次計算,或者可以計算一次並私下存儲在類中。

Here are two illustrations. The first snippet is to be avoided:

這是兩個插圖。第一個片段是要避免的:

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

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

The second is preferable:

第二個是優選的:

string connectionString = ConfigurationManager.AppSettings("ConnectionString")

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

The problem here is that AppSettings() actually has to unbox the AppSettings collection everytime a value is retrieved:

這里的問題是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;
    }
}

#5


1  

Debugging the latter is going to be harder if you want to see the intermediate state, and single step through the stages.

如果你想看到中間狀態,並且單步進入階段,那么調試后者會更難。

I would go for readability over the amount of screen real estate used here since performance is a wash.

我會考慮這里使用的屏幕空間量的可讀性,因為性能是一種清洗。

#6


1  

I call it chaining.

我稱之為鏈接。

You are asking the wrong question.

你問的是錯誤的問題。

What you need to ask is: Which is more readable?

你需要問的是:哪個更具可讀性?

If chaining makes the code easier to read and understand than go ahead and do it.

如果鏈接使代碼更容易閱讀和理解,那么就去做吧。

If however, it obfuscates, then don't.

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

Any performance optimizations are non-existant. Don't optimize code, optimize algorithms.

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

So, if you are going to be calling Item(1) and Item(2), then by chaining, You'll be creating the same object over and over again which is a bad algorithm.

所以,如果你打算調用Item(1)和Item(2),那么通過鏈接,你將一遍又一遍地創建同一個對象,這是一個糟糕的算法。

In that case, then the first option is better, as you don't need to recreate the adapter each time.

在這種情況下,第一個選項更好,因為您不需要每次都重新創建適配器。

#7


1  

One reason against 'chaining' is the Law of Demeter which would suggest that your code is fragile in the face of changes to LookupCodeDataTable.

反對“鏈接”的一個原因是Demeter法則表明,在LookupCodeDataTable發生變化時,您的代碼很脆弱。

You should add a function like this:

你應該添加這樣的函數:

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

and call it like this:

並稱之為:

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

Now getMeaning() is available to be called in many other places and if LookupCodeDataTable changes, then you only have to change getMeaning() to fix it.

現在可以在許多其他地方調用getMeaning(),如果LookupCodeDataTable發生變化,那么你只需要更改getMeaning()來修復它。

#8


0  

The structure is still created, you just do not have a reference for it.

結構仍然是創建的,你只是沒有它的參考。

#9


0  

This:

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

and this:

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

are completely equivalent.

是完全相同的。

In the first example, you've got an explicit temporary reference (dtLookupTable). In the second example, the temporary reference is implicit. Behind the scenes, the compiler will almost certainly create the same code for both of these. Even if it didn't emit the same code, the extra temporary reference is extremely cheap.

在第一個示例中,您有一個顯式的臨時引用(dtLookupTable)。在第二個示例中,臨時引用是隱式的。在幕后,編譯器幾乎肯定會為這兩者創建相同的代碼。即使它沒有發出相同的代碼,額外的臨時引用也非常便宜。

However, I'm not sure if this line:

但是,我不確定這行是否:

Dim dtLookupCode As New LookupCodeDataTable()

is efficient. It looks to me like this creates a new LookupCodeDataTable which is then discarded when you overwrite the variable in the later statement. I don't program in VB, but I would expect that this line should be:

很有效率。在我看來,這會創建一個新的LookupCodeDataTable,然后在后面的語句中覆蓋變量時將其丟棄。我不用VB編程,但我希望這行應該是:

Dim dtLookupCode As LookupCodeDataTable

The reference is cheap (probably free), but constructing an extra lookup table may not be.

引用很便宜(可能是免費的),但構建額外的查找表可能不是。

#10


0  

It's the same unless you need to refer to the returned objects by taLookupCode.GetDataByCodeAndValue("EmpStatus", "FULL") or Item(0) multiple times. Otherwise, you don't know if the runtime for this function is log(n) or n, so for the best bet, I would assign a reference to it.

除非您需要多次通過taLookupCode.GetDataByCodeAndValue(“EmpStatus”,“FULL”)或Item(0)引用返回的對象,否則它是相同的。否則,你不知道這個函數的運行時是log(n)還是n,所以為了最好的選擇,我會為它分配一個引用。

#11


0  

Besides maintainability, here's another reason to avoid chaining: Error checking.

除了可維護性之外,這是避免鏈接的另一個原因:錯誤檢查。

Yes, you can wrap the whole thing in try/catch, and catch every exception that any part of the chain can throw.

是的,你可以將整個東西包裝在try / catch中,並捕獲鏈中任何部分都可以拋出的每個異常。

But if you want to validate results in between calls without try/catch, you have to split things apart. For instance:

但是如果你想在沒有try / catch的情況下在調用之間驗證結果,你必須將事情分開。例如:

  • What happens when GetDataByCodeAndValue returns null?
  • 當GetDataByCodeAndValue返回null時會發生什么?

  • What if it returns an empty list?
  • 如果它返回一個空列表怎么辦?

You can't check for these values without try/catch if you're chaining.

如果您正在鏈接,則無法在沒有try / catch的情況下檢查這些值。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2008/09/19/72f52d9900fd549b23db655247395785.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com