[rozważania] Porównywanie stringów

0

W tym wątku poruszono kwestię porównania dwóch stringów i nie chcąc tam siać zamętu rozpocząłem nowy wątek.

Zazwyczaj pisałem

if (string1 == "abc") {}

ale widzę, że ta wersja jest niezalecana. To dość dziwne, że kompilator nie zamienia jej w takim razie na wersję "lepszą" - dlaczego?

Do wyboru mamy jeszcze:

if (string1.CompareTo("abc")) {}

oraz

if (string1.Equals("abc")) {}

do tego jeśli porównujemy string1 z łańcuchem pustym "" to można jeszcze użyć:

if (string1.Length == 0) { }

Której wersji używać najlepiej, dlaczego i dlaczego kompilator sam nie dobierze optymalnej, jeśli da się to prosto określić?

Jedyne, co kiedyś wyczytałem, to powinno się stosować Equals i dodać odpowiednie CultureInfo jeśli program jest wielojęzyczny i porównuje dane wprowadzane przez użytkownika [np. filtr czy wyszukiwanie].

0

Mam taki artykuł na temat porównywania stringów: http://www.codeproject.com/cs[...]elect=1675447&tid=1675447

Co do pytania dlaczego konstrukcja if (string1 == "abc") {}nie jest zamieniana na inną, lepszą to według mnie nie jest zamieniana ponieważ wszystkie te podane powyżej konstrukcje są poprawne i różnią się jedynie czasem wykonywania i ilością potrzebnej pamięci. Są jedynie zalecenia co do tego co lepiej i efektywniej wykorzystywać to jednak nie powód aby odbierać tę dowolność i narzucać programiście konkretny sposób porównywania.

0

Witam :)

Dawno nie pisalem tu ale cos i od siebie powiem:

Dla wgladu zamieszczam kody funkcji Equlas:


    public static bool Equals (string a, string b)

            {
                if (a == b)
                {
                    return true;
                }
                else if (a == null)
                {
                    return false;
                }
                else if (b != null)
                {
                    return string.EqualsHelper (a, b);
                }
                else
                {
                    return false;
                }
            }

private static unsafe bool EqualsHelper (string strA, string strB)

            {
                char* char_Ptr3;
                char* char_Ptr4;
                int i1 = strA.Length;
                if (i1 != strB.Length)
                {
                    return false;
                }
                else
                {
                    fixed (char* char_Ptr1 = (strA + RuntimeHelpers.OffsetToStringData))
                    {
                        fixed (char* char_Ptr2 = (strB + RuntimeHelpers.OffsetToStringData))
                        {
                            char_Ptr3 = char_Ptr1;
                            char_Ptr4 = char_Ptr2;
                            while (i1 >= 10)
                            {
                                if ((((((* char_Ptr3) != (* char_Ptr4)) || ((* (char_Ptr3 + 2)) != (* (char_Ptr4 + 2)))) || ((* (char_Ptr3 + 4)) != (* (char_Ptr4 + 4)))) || ((* (char_Ptr3 + 6)) != (* (char_Ptr4 + 6)))) || ((* (char_Ptr3 + 8)) != (* (char_Ptr4 + 8))))
                                {
                                    break;
                                }
                                char_Ptr3 += 20;
                                char_Ptr4 += 20;
                                i1 -= 10;
                            }
                            while ((i1 > 0) && ((* char_Ptr3) == (* char_Ptr4)))
                            {
                                char_Ptr3 += 4;
                                char_Ptr4 += 4;
                                i1 -= 2;
                            }
                            return (i1 <= 0);
                        }
                    }
                }
            }

funkcji Compare:

public int CompareTo (string strB)

            {
                if (strB != null)
                {
                    return CultureInfo.CurrentCulture.CompareInfo.Compare (this, strB, CompareOptions.None);
                }
                else
                {
                    return 1;
                }
            }

public static int Compare (string strA, string strB)

            {
                return CultureInfo.CurrentCulture.CompareInfo.Compare (strA, strB, CompareOptions.None);
            }

//CompareInfo.Compare

public virtual int Compare (string string1, string string2)

            {
                return this.Compare (string1, string2, CompareOptions.None);
            }

//CompareInfo.Compare
        public unsafe virtual int Compare (string string1, string string2, CompareOptions options)

            {
                if (options == CompareOptions.OrdinalIgnoreCase)
                {
                    return string.Compare (string1, string2, StringComparison.OrdinalIgnoreCase);
                }
                else if ((options & CompareOptions.Ordinal) != CompareOptions.None)
                {
                    if (options == CompareOptions.Ordinal)
                    {
                        if (string1 == null)
                        {
                            if (string2 != null)
                            {
                                return -1;
                            }
                            else
                            {
                                return 0;
                            }
                        }
                        if (string2 != null)
                        {
                            return string.nativeCompareOrdinal (string1, string2, false);
                        }
                        else
                        {
                            return 1;
                        }
                    }
                    throw new ArgumentException (Environment.GetResourceString ("Argument_CompareOptionOrdinal"), "options");
                }
                else if ((options & (~ (CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.StringSort))) != CompareOptions.None)
                {
                    throw new ArgumentException (Environment.GetResourceString ("Argument_InvalidFlag"), "options");
                }
                else
                {
                    if (string1 == null)
                    {
                        if (string2 != null)
                        {
                            return -1;
                        }
                        else
                        {
                            return 0;
                        }
                    }
                    if (string2 == null)
                    {
                        return 1;
                    }
                    else if (! this.IsSynthetic)
                    {
                        return CompareInfo.Compare (this.m_pSortingTable, this.m_sortingLCID, string1, string2, options);
                    }
                    else if (options != CompareOptions.Ordinal)
                    {
                        return CompareInfo.nativeCompareString (this.m_sortingLCID, string1, 0, string1.Length, string2, 0, string2.Length, CompareInfo.GetNativeCompareFlags (options));
                    }
                    else
                    {
                        return CompareInfo.Compare (CultureInfo.InvariantCulture.CompareInfo.m_pSortingTable, this.m_sortingLCID, string1, string2, options);
                    }
                }
            }

Sami wysnujcie wnioski ;)
niestety nie posiadam kodów funkcji operatorowej string.==

0

imho różnice mogą pojawić się przy logice - jeśli ustawienia regionalne i językowe będą specyficzne, mogą pojawić się błędy. Fajny przykład (Turkish-I Problem) podany jest na http://msdn2.microsoft.com/en-us/library/ms973919.aspx.

A jeśli chodzi o wybór metody - wydaje mi się, że dopóki w porównaniach nie używamy stringów mogących pochodzić spoza kodu aplikacji, można oprzeć się choćby na "==".

Jeśli chodzi o wydajność - we wspomnianym wątku cytowałem wspomniany tutaj artykuł z CodeProjecta (choć trochę wyrwałem cytat z kontekstu :)). Małe porównanie jest też tu: http://dotnetjunkies.com/WebLog/chris.taylor/archive/2004/05/18/13927.aspx

A tu parę off-topic'owych linków:

0

MrC - wiesz, wydaje mi sie ze wszyscy umieja uzywac Reflector'a, nie trzeba wiec smiecic bukwami kodu

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0