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.

: Bearbeitet durch User
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.