[英]In VB.NET, C#, etc., does the one-dot rule automatically get optimized into the code?
在VB.NET,C#等中,這樣的東西不會得到優化,是嗎?
'Bad
a.B.C.DoSomething1()
a.B.C.DoSomething2()
a.B.C.X = 5
DoSomething3(a.B.C.D)
'Good
Dim cachedReference As ClassOfC = a.B.C
cachedReference.DoSomething1()
cachedReference.DoSomething2()
cachedReference.X = 5
DoSomething3(cachedReference.D)
至少在ECMA類型的語言中,這是一個好習慣,要盡量減少它進入a
,然后轉到其B
字段/屬性,最后到其C
字段/屬性。 我認為這通常是任何典型的面向對象或過程語言中的經驗法則,除非至少有一個明確的期望,那就是它將像編譯器/ jit / etc那樣得到優化。 無論如何。 在典型的.NET(特別是VB.NET和C#)中如何處理?
例如,這似乎沒有提到單點規則,至少與這兩種語言之一有關: https : //msdn.microsoft.com/zh-cn/library/ms973839.aspx 。 另一方面,如果對屬性進行一般設置,我會感到非常驚訝,因為它們是有效的方法。 如果這樣做,並且僅當它們是字段,甚至可能是完全無關緊要的屬性時,這樣做似乎更有意義。
好吧,出於好奇,我繼續嘗試了一下。
給定以下類別:
public class Foo
{
public Bar Bar { get; set;}
}
public class Bar
{
public Baz Baz { get; set;}
}
public class Baz
{
public string One { get; set; } = string.Empty;
public string Two { get; set; } = string.Empty;
public bool BothPopulated() => !(string.IsNullOrWhiteSpace(One) || string.IsNullOrWhiteSpace(Two));
}
public class FooFactory
{
public static Foo Create() => new Foo { Bar = new Bar { Baz = new Baz { One = "Hello", Two = "World" } } };
}
和以下方法:
void Main()
{
var foo = FooFactory.Create();
var cached = foo.Bar.Baz;
Console.WriteLine(cached.One);
Console.WriteLine(cached.Two);
Console.WriteLine(cached.BothPopulated());
var fooTwo = FooFactory.Create();
Console.WriteLine(fooTwo.Bar.Baz.One);
Console.WriteLine(fooTwo.Bar.Baz.Two);
Console.WriteLine(fooTwo.Bar.Baz.BothPopulated());
}
LinqPad將釋放模式下的main發出的IL報告為
IL_0000: call UserQuery+FooFactory.Create
IL_0005: callvirt UserQuery+Foo.get_Bar
IL_000A: callvirt UserQuery+Bar.get_Baz
IL_000F: dup
IL_0010: callvirt UserQuery+Baz.get_One
IL_0015: call System.Console.WriteLine
IL_001A: dup
IL_001B: callvirt UserQuery+Baz.get_Two
IL_0020: call System.Console.WriteLine
IL_0025: callvirt UserQuery+Baz.BothPopulated
IL_002A: call System.Console.WriteLine // <- End of cached portion
IL_002F: call UserQuery+FooFactory.Create
IL_0034: dup
IL_0035: callvirt UserQuery+Foo.get_Bar
IL_003A: callvirt UserQuery+Bar.get_Baz
IL_003F: callvirt UserQuery+Baz.get_One
IL_0044: call System.Console.WriteLine
IL_0049: dup
IL_004A: callvirt UserQuery+Foo.get_Bar
IL_004F: callvirt UserQuery+Bar.get_Baz
IL_0054: callvirt UserQuery+Baz.get_Two
IL_0059: call System.Console.WriteLine
IL_005E: callvirt UserQuery+Foo.get_Bar
IL_0063: callvirt UserQuery+Bar.get_Baz
IL_0068: callvirt UserQuery+Baz.BothPopulated
IL_006D: call System.Console.WriteLine
IL_0072: ret
因此,看起來您確實通過不每次都鑽取屬性來保存了一些callvirt。 我無法回答這是否會對運行時的JIT產生任何可衡量的影響,但是它確實留下了較小的IL占用空間。
我懷疑它對運行時性能的影響基本上為零。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.