2016-01-25 17 views
8

Czy za pomocą operatora null-conditional duplicate null checks? Na przykładCzy operator Null-Conditional jest zoptymalizowany dla kolejnych stron usługodawców lub czy powoduje duplikowanie czeków?

var x = instance?.Property1; 
var y = instance?.Property2; 

Czy to uzyskać skompilowany w ten sposób:

if (instance != null) 
{ 
    var x = instance.Property1; 
    var y = instance.Property2; 
} 

Albo to?

if (instance != null) 
{ 
    var x = instance.Property1; 
} 

if (instance != null) 
{ 
    var y = instance.Property2; 
} 

Czy w pierwszym przypadku różnica między dwoma liniami jest inna? Innymi słowy, jak inteligentny jest kompilator/optymalizator?

+3

Tak wiele nowych funkcji, ale wciąż czekam na moje typy NON-NULL. *Westchnienie*. – user2864740

+0

@ user2864740 hear hear –

Odpowiedz

6

Kompilator wydaje się być dość nieświadomy tego.

Kod:

var x = instance?.Property1; 
var y = instance?.Property2; 

... kompiluje jako non-zoptymalizowane do:

IL_0000: nop   
IL_0001: newobj  UserQuery+Class..ctor 
IL_0006: stloc.0  // instance 
IL_0007: ldloc.0  // instance 
IL_0008: brtrue.s IL_000D 
IL_000A: ldnull  
IL_000B: br.s  IL_0013 
IL_000D: ldloc.0  // instance 
IL_000E: ldfld  UserQuery+Class.Property1 
IL_0013: stloc.1  // x 
IL_0014: ldloc.0  // instance 
IL_0015: brtrue.s IL_001A 
IL_0017: ldnull  
IL_0018: br.s  IL_0020 
IL_001A: ldloc.0  // instance 
IL_001B: ldfld  UserQuery+Class.Property2 
IL_0020: stloc.2  // y 
IL_0021: ret   

Class..ctor: 
IL_0000: ldarg.0  
IL_0001: call  System.Object..ctor 
IL_0006: nop   
IL_0007: ret   

... i zoptymalizowany jako:

IL_0000: newobj  UserQuery+Class..ctor 
IL_0005: dup   
IL_0006: dup   
IL_0007: brtrue.s IL_000C 
IL_0009: pop   
IL_000A: br.s  IL_0012 
IL_000C: ldfld  UserQuery+Class.Property1 
IL_0011: pop   
IL_0012: dup   
IL_0013: brtrue.s IL_0017 
IL_0015: pop   
IL_0016: ret   
IL_0017: ldfld  UserQuery+Class.Property2 
IL_001C: pop   
IL_001D: ret   

Class..ctor: 
IL_0000: ldarg.0  
IL_0001: call  System.Object..ctor 
IL_0006: ret   

równocześnie wyraźnie z dwóch kontrola oddziałów.

+0

Witaj, to jest świetne! :) poza tematem, ale zastanawiam się, jak uzyskać IL w tym formacie? – Ian

+3

@Ian Prawie definitywnie z LINQPad :) – Rob

+0

@Rob cześć, dzięki za wskazówki! : DI przeczytać zaakceptowaną odpowiedź: http://stackoverflow.com/questions/3326571/how-can-i-view-msil-cil-generated-by-c-sharp-compiler-why-is-it-called -montuj i próbuj dowiedzieć się, co to znaczy przez '.text' w pliku PE. Ale jeśli istnieje alternatywny sposób patrzenia na kod zespołu (jak pokazuje inna odpowiedź w łączu), po prostu sprawdziłbym to. :) – Ian

5

Wykonuje dwie oddzielne If..Else sprawdza przypisania za pomocą operatora warunkowego null w Twojej sprawie. Poniżej jest zdemontowany przykładowy kod

Kod źródłowy:

public class nulltest 
{ 
    public void test() 
    { 
     var instance = new testclass(); 
     var x = instance?.prop1; 
     var y = instance?.prop2; 
    } 
} 

public class testclass 
{ 
    public int prop1; 
    public int prop2; 
} 

kod demontażu (ILSpy):

public class nulltest 
{ 
    public void test() 
    { 
     testclass testclass = new testclass(); 
     if (testclass == null) 
     { 
      int? arg_20_0 = null; 
     } 
     else 
     { 
      new int?(testclass.prop1); 
     } 
     if (testclass == null) 
     { 
      int? arg_3A_0 = null; 
     } 
     else 
     { 
      new int?(testclass.prop2); 
     } 
    } 
} 

użyłem int jak rodzaj własności, ale powyższe należy uznać za prawdziwe dla każdego inny przypadek.

5

Kompilator jest rygorystyczny, pomyśl o tym kodzie.

class Tricky 
{ 
    public int Property1 
    { 
     get 
     { 
      Program.instance = null; 
      return 1; 
     } 
    } 

    public int Property2 
    { 
     get 
     { 
      return 2; 
     } 
    } 
} 

class Program 
{ 
    public static Tricky instance = new Tricky(); 

    public static void Main(string[] arg) 
    { 
     var x = instance?.Property1; 
     var y = instance?.Property2; 
     //what do you think the values of x,y 
    } 
} 

Spodziewany wynik to: x == 1, y is null. Ale jeśli kompilator zoptymalizuje kod przy użyciu jednej instrukcji if, wyrzuci NullReferenceException. Co oznacza, że ​​używanie jednej instrukcji if nie jest inteligentną optymalizacją, nie jest optymalizacją, ponieważ jest NIEPRAWIDŁOWA.

+0

Ale wiesz, nikt nie pisze takiego kodu, prawda? Oh poczekaj ... –

+0

@NelsonRothermel True. Jednak kompilator nie powinien działać zgodnie z takimi założeniami, powyższy kod jest całkowicie legalny z widoku językowego. –

+0

Nie wspominając już o bezpieczeństwie gwintów. –

Powiązane problemy