الاختلافات في سلسلة مقارنة طرق في C#




string comparison (8)

إذا كنت تشعر بالفضول حول الاختلافات في أساليب BCL ، Reflector هو صديقك :-)

أتبع هذه الإرشادات:

المطابقة التامة: EDIT: لقد استخدمت دائمًا == عامل التشغيل على مبدأ أنه داخل Equals (string ، string) يتم استخدام الكائن object = = لمقارنة مراجع الكائن ولكن يبدو أن strA.Equals (strB) لا يزال 1-11٪ أسرع عموما من string.Equals (strA ، strB) ، strA == strB ، و string.CompareOrdinal (strA ، strB). أنا حلقة اختبار مع StopWatch على كل من القيم سلسلة interned / غير interned ، مع أطوال سلسلة نفس / مختلفة ، وأحجام مختلفة (1B إلى 5MB).

strA.Equals(strB)

مباراة سهلة القراءة (الثقافات الغربية ، غير حساسة لحالة الأحرف):

string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0

مباراة سهلة القراءة (جميع الثقافات الأخرى ، حالة غير حساسة / اللهجة / kana / الخ التي حددتها CultureInfo):

string.Compare(strA, strB, myCultureInfo) == 0

تطابق قابل للقراءة مع القواعد المخصصة (جميع الثقافات الأخرى):

CompareOptions compareOptions = CompareOptions.IgnoreCase
                              | CompareOptions.IgnoreWidth
                              | CompareOptions.IgnoreNonSpace;
string.Compare(strA, strB, CultureInfo.CurrentCulture, compareOptions) == 0

مقارنة السلسلة في C # بسيطة جدا. في الواقع هناك العديد من الطرق للقيام بذلك. لقد أدرجت بعض في الكتلة أدناه. ما يثير فضولنا هو الاختلافات بينهم وبين متى يجب استخدام أحدهما على الآخرين؟ هل يجب تجنب أحد بأي ثمن؟ هل هناك المزيد لم أدرجه؟

string testString = "Test";
string anotherString = "Another";

if (testString.CompareTo(anotherString) == 0) {}
if (testString.Equals(anotherString)) {}
if (testString == anotherString) {}

(ملاحظة: أنا أبحث عن المساواة في هذا المثال ، ليس أقل من أو أكبر من ولكن لا تتردد في التعليق على ذلك أيضًا)


اختلاف واحد كبير ملاحظة هو .Equals () سيتم طرح استثناء إذا كانت السلسلة الأولى فارغة ، بينما لن ===.

       string s = null;
        string a = "a";
        //Throws {"Object reference not set to an instance of an object."}
        if (s.Equals(a))
            Console.WriteLine("s is equal to a");
        //no Exception
        if(s==a)
            Console.WriteLine("s is equal to a");

في النماذج التي ذكرتها هنا ، لا يوجد فرق كبير بين الاثنين. ينتهي CompareTo باستدعاء طريقة CompareInfo التي تقوم بإجراء مقارنة باستخدام الثقافة الحالية ؛ يسمى Equals قبل == المشغل.

إذا كنت تفكر في الحمل الزائد ، فستصبح الأمور مختلفة. Compare و == يمكن فقط استخدام الثقافة الحالية لمقارنة سلسلة. يمكن أن Equals و StringComparison حجة تعداد StringComparison التي تتيح لك تحديد مقارنات حساسة للثقافة أو غير حساسة لحالة الأحرف. فقط String.Compare يسمح لك بتحديد CultureInfo وإجراء مقارنات باستخدام ثقافة أخرى غير الثقافة الافتراضية.

بسبب تنوعها ، أجد أنني أستخدم String.Compare أكثر من أي طريقة مقارنة أخرى. يتيح لي تحديد ما أريده بالضبط.


فيما يلي القواعد الخاصة بكيفية عمل هذه الوظائف:

stringValue.CompareTo(otherStringValue)

  1. null يأتي قبل سلسلة
  2. ويستخدم CultureInfo.CurrentCulture.CompareInfo.Compare ، مما يعني أنه سيستخدم مقارنة تعتمد على البيانات. قد يعني هذا أن ß ستقارن بـ SS في ألمانيا ، أو ما شابه

stringValue.Equals(otherStringValue)

  1. لا تعتبر null مساوية لأي شيء
  2. إلا إذا قمت بتحديد خيار StringComparison ، فسوف يستخدم ما يشبه فحصًا للمساواة الترتيبية المباشرة ، بمعنى أن ß ليس هو نفسه SS ، بأي لغة أو ثقافة

stringValue == otherStringValue

  1. ليس هو نفسه stringValue.Equals() .
  2. يقوم عامل التشغيل == باستدعاء القيمة الساكنة Equals(string a, string b) (والتي بدورها تذهب إلى EqualsHelper الداخلي EqualsHelper المقارنة.
  3. استدعاء .Equals() على سلسلة null تحصل على استثناء مرجع null ، في حين أن == لا.

Object.ReferenceEquals(stringValue, otherStringValue)

فقط يتحقق من أن المراجع هي نفسها ، بمعنى أنها ليست مجرد سلسلتين لها نفس المحتويات ، فأنت تقارن كائن سلسلة بنفسها.

لاحظ أنه مع وجود الخيارات الموجودة أعلاه التي تستخدم مكالمات الأسلوب ، توجد زيادة في التحميل تحتوي على المزيد من الخيارات لتحديد كيفية المقارنة.

نصيحتي إذا كنت ترغب فقط في التحقق من المساواة هو أن .CompareTo ما إذا كنت تريد استخدام مقارنة تعتمد على ثقافة أم لا ، ومن ثم استخدم .CompareTo أو .Equals ، اعتمادا على الاختيار.


لا يعني ذلك أن الأداء عادة ما يكون مهمًا بنسبة 99٪ من المرات التي تحتاج فيها إلى ذلك ، ولكن إذا كان عليك القيام بذلك في حلقة عدة ملايين المرات ، فإنني أقترح عليك بشدة أن تستخدم .Equals أو == لأنه بمجرد العثور على شخصية التي لا تتطابق مع أنه يرمي كل شيء على أنه خطأ ، ولكن إذا استخدمت CompareTo ، فسيكون عليك معرفة أي حرف أقل من الآخر ، مما يؤدي إلى وقت أداء أسوأ قليلاً.

إذا كان تطبيقك سيعمل في بلدان مختلفة ، فإنني أوصيك بأن تلقي نظرة على آثار CultureInfo وربما تستخدم .Equals. نظرًا لأنني لا أكتب إلا التطبيقات للولايات المتحدة (ولا يهمني ما إذا كانت لا تعمل بشكل صحيح من قِبل شخص ما) ، فأنا أستخدم دائمًا == فقط.


مع .EQUALS ، يمكنك أيضا الحصول على خيارات StringComparison. سهل جدا لتجاهل القضية وغيرها من الأشياء.

راجع للشغل ، وهذا سوف يقيّم كاذبة

string a = "myString";
string b = "myString";

return a==b

بما أن = = يقارن قيم a و b (وهي مؤشرات) ، فسيتم تقييم هذا فقط إلى true إذا كانت المؤشرات تشير إلى نفس الكائن في الذاكرة. .Equals dereferences المؤشرات ويقارن القيم المخزنة في المؤشرات. a.Equals (ب) سيكون صحيحا هنا.

وإذا قمت بتغيير b إلى:

b = "MYSTRING";

ثم a.Equals (ب) غير صحيح ، ولكن

a.Equals(b, StringComparison.OrdinalIgnoreCase) 

سيكون صحيحا

a.CompareTo (b) يستدعي الدالة CompareTo الخاصة بالسلسلة التي تقارن القيم في المؤشرات وتعيد <0 إذا كانت القيمة المخزنة في a أقل من القيمة المخزنة عند b ، تُرجع 0 إذا كانت a.Equals (b) صحيحة ، و > 0 خلاف ذلك. ومع ذلك ، فهذا أمر حساس لحالة الأحرف ، وأعتقد أن هناك خيارات محتملة لـ CompareTo لتجاهل الحالة ومثل هذه الحالة ، ولكن ليس لدينا وقت للنظر الآن. وكما ذكر آخرون بالفعل ، فسيتم القيام بذلك من أجل الفرز. المقارنة من أجل المساواة بهذه الطريقة يؤدي إلى نفقات غير ضرورية.

أنا متأكد من مغادرتي للأشياء ، ولكن أعتقد أن هذا يجب أن يكون معلومات كافية لبدء التجريب إذا كنت بحاجة إلى مزيد من التفاصيل.


يقارن CompareTo السلسلة مع كائن سلسلة وإرجاع قيمة int. إذا كانت القيمة 0 ، فهذا يعني أن السلاسل متساوية.

string country = "southindia";
object ob1 = country.Clone();
Console.WriteLine( country.CompareTo(ob1));

string country = "southindia";
string cou = "insia";
int n = country.CompareTo(cou);
Console.WriteLine( n );

يمكن العثور على شرح جيد وممارسات حول مشكلات مقارنة السلسلة في المقالة توصيات جديدة لاستخدام سلاسل في Microsoft .NET 2.0 وكذلك في أفضل الممارسات لاستخدام سلاسل في .NET Framework .

كل من الأسلوب المذكور (وغيرها) له غرض معين. الفرق الرئيسي بينهما هو نوع التعداد StringComparison الذي يستخدمه بشكل افتراضي. هناك عدة خيارات:

  • CurrentCulture
  • CurrentCultureIgnoreCase
  • InvariantCulture
  • InvariantCultureIgnoreCase
  • ترتيبي
  • OrdinalIgnoreCase

كل نوع من أنواع المقارنة المذكورة أعلاه يستهدف حالة استخدام مختلفة:

  • ترتيبي
    • معرفات داخلية حساسة لحالة الأحرف
    • معرفات حساسة لحالة الأحرف في معايير مثل XML و HTTP
    • إعدادات الأمان الحساسة لحالة الأحرف
  • OrdinalIgnoreCase
    • معرفات داخلية غير حساسة لحالة الأحرف
    • معرفات حساسة لحالة الأحرف في معايير مثل XML و HTTP
    • مسارات الملفات (في Microsoft Windows)
    • مفاتيح التسجيل / القيم
    • متغيرات البيئة
    • معرفات الموارد (أسماء المقابض ، على سبيل المثال)
    • إعدادات الأمان غير الحساسة لحالة الأحرف
  • InvariantCulture أو InvariantCultureIgnoreCase
    • بعض استمرت البيانات ذات الصلة لغويا
    • عرض البيانات اللغوية التي تتطلب ترتيبًا ثابتًا
  • CurrentCulture أو CurrentCultureIgnoreCase
    • البيانات المعروضة للمستخدم
    • معظم مدخلات المستخدم

لاحظ أن تعداد StringComparison وكذلك الأحمال الزائدة لطرق مقارنة السلسلة موجود منذ .NET 2.0.

String.CompareTo Method (String)

هو في الواقع نوع تنفيذ آمن من IComparable.CompareTo الأسلوب . التفسير الافتراضي: CurrentCulture.

الاستعمال:

تم تصميم طريقة CompareTo في المقام الأول للاستخدام في عمليات الفرز أو الترتيب الأبجدي

وهكذا

تنفيذ واجهة IComparable سيستخدم بالضرورة هذه الطريقة

طريقة String.Compare

عضو ثابت في فئة String والذي يحتوي على الكثير من الأحمال الزائدة. التفسير الافتراضي: CurrentCulture.

كلما كان ذلك ممكناً ، يجب استدعاء الحمل الزائد من طريقة مقارنة يتضمن معلمة StringComparison.

طريقة String.Equals

تجاوز من فئة كائن وتغاضى عن سلامة نوع. التفسير الافتراضي: ترتيبي. لاحظ أن:

تتضمن أساليب المساواة في فئة السلسلة الأكوام الساكنة والمشغل الثابت == وأسلوب المثالية يساوي .

فئة StringComparer

هناك أيضًا طريقة أخرى للتعامل مع مقارنات السلاسل خاصةً تهدف إلى الفرز:

يمكنك استخدام الفئة StringComparer لإنشاء مقارنة خاصة بكل نوع لفرز العناصر في مجموعة عامة. تستخدم فئات مثل Hashtable و Dictionary و SortedList و SortedList الفئة StringComparer لأغراض الفرز.





comparison