Forum: PC-Programmierung c#: Anweisung in if-Abfrage safe?


von J. W. (nuernberger)


Lesenswert?

1
string sopt=null;
2
if (str.StartsWith(sopt="+UUSORD:")||
3
   str.StartsWith(sopt="+USORD:"))
4
{
5
  // sopt ist entweder "+UUSORD:" oder "+USORD:"
6
}

Ich möchte eine If-Abfrage mit zwei or-conditions vereinfachen.
Damit ich innerhalb des if-branches noch unterscheiden kann, welcher der 
beiden werte zutrifft, halte ich diesen Wert in einer Variablen fest 
(sopt).
In C habe ich das schon immer so gemacht.
Mit Mono-Projekt in C# funktioniert es.
Frage: Funktioniert das generell (d.h. auch in Visual Studio)?
Ist sowas sauber programmiert? Oder sollte man doch 2 If-Branches 
nehmen?

von Felix U. (ubfx)


Lesenswert?

J. W. schrieb:
> Ich möchte eine If-Abfrage mit zwei or-conditions vereinfachen.
> Damit ich innerhalb des if-branches noch unterscheiden kann, welcher der
> beiden werte zutrifft, halte ich diesen Wert in einer Variablen fest
> (sopt).
> In C habe ich das schon immer so gemacht.
Da ist das zwar auch nicht schön, aber noch vertretbar weil man da dann 
innerhalb des if-blocks nur einen Pointer und kein ganzes Objekt nochmal 
vergleichen muss.

> Mit Mono-Projekt in C# funktioniert es.
> Frage: Funktioniert das generell (d.h. auch in Visual Studio)?
Ja.
> Ist sowas sauber programmiert?
Nein. Einen string zu benutzen ist mit Sicherheit nicht sauber 
programmiert. Konkret sieht das dann nämlich so aus:
1
//string test = "123abc123";
2
IL_000c: ldstr "123abc123"
3
IL_0011: stloc.0
4
5
//string prefix = null;
6
IL_0012: ldnull
7
IL_0013: stloc.1
8
9
//if (test.StartsWith(prefix = "abc") ||
10
//  test.StartsWith(prefix = "123"))
11
IL_0014: ldloc.0
12
IL_0015: ldstr "abc"
13
IL_001a: dup
14
IL_001b: stloc.1
15
IL_001c: callvirt instance bool [mscorlib]System.String::StartsWith(string)
16
IL_0021: brtrue.s IL_0032
17
18
IL_0023: ldloc.0
19
IL_0024: ldstr "123"
20
IL_0029: dup
21
IL_002a: stloc.1
22
IL_002b: callvirt instance bool [mscorlib]System.String::StartsWith(string)
23
IL_0030: brfalse.s IL_006d
24
25
// {
26
// if (prefix == "abc")
27
IL_003d: ldloc.1
28
IL_003e: ldstr "abc"
29
IL_0043: call bool [mscorlib]System.String::op_Equality(string, string)
30
IL_0048: brfalse.s IL_0055
31
32
// if (prefix == "123")
33
IL_0055: ldloc.1
34
IL_0056: ldstr "123"
35
IL_005b: call bool [mscorlib]System.String::op_Equality(string, string)
36
IL_0060: brfalse.s IL_006d

Visual Studio mit Standardeinstellungen optimiert das also schon mal 
nicht. Innerhalb des if-blocks werden die Strings nochmal neu auf den 
Stack gepusht und dann wird eine lib-Funktion für den Vergleich 
aufgerufen.

Schöner und effizienter geht es so:
1
bool b_pre_abc = test.StartsWith("abc"),
2
b_pre_123 = test.StartsWith("123");
3
4
if (b_pre_123 || b_pre_abc)
5
{
6
    MessageBox.Show("Match");
7
8
    if (b_pre_abc)
9
        ...
10
    if (b_pre_123)
11
        ...
12
}

Das sieht dann nämlich innerhalb des if-blocks schon wesentlich 
schlanker aus:
1
//if (b_pre_abc)
2
IL_0095: ldloc.2
3
IL_0096: brfalse.s IL_00a3
4
5
//if (b_pre_123)
6
IL_00a3: ldloc.3
7
IL_00a4: brfalse.s IL_00b1

Man spart sich also zwei library calls, viele Stringoperationen und 
gewinnt auch noch Lesbarkeit.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.