سؤال

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

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

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

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

هل كانت مفيدة؟

المحلول

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

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 للقيام بهذه المقارنة.
  3. الاتصال .Equals() على null تحصل السلسلة null استثناء مرجعي، أثناء التشغيل == لا.

Object.ReferenceEquals(stringValue, otherStringValue)

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


لاحظ أنه مع الخيارات المذكورة أعلاه التي تستخدم استدعاءات الطريقة، هناك حمولات زائدة مع المزيد من الخيارات لتحديد كيفية المقارنة.

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

نصائح أخرى

من MSDN:

"تم تصميم طريقة المقارنة في المقام الأول للاستخدام في عمليات الفرز أو الأبجدية.لا ينبغي استخدامه عندما يكون الغرض الأساسي من استدعاء الطريقة هو تحديد ما إذا كانت سلسلتين مكافئات.لتحديد ما إذا كانت سلسلتين متكافئتين ، اتصل بالطريقة المتساوية. "

يقترحون استخدام .Equals بدلاً من .CompareTo عندما تبحث فقط عن المساواة.لست متأكدا إذا كان هناك فرق بين .Equals و == ل string فصل.سأستخدم في بعض الأحيان .Equals أو Object.ReferenceEquals بدلاً من == لفصولي الخاصة في حالة قدوم شخص ما في وقت لاحق وإعادة تعريف == عامل لتلك الفئة.

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

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

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

strA.Equals(strB)

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

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

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

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

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

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

مثل إد قال، يتم استخدام CompareTo للفرز.

ومع ذلك، هناك فرق بين .Equals و==.

== يقرر بشكل أساسي الكود التالي:

if(object.ReferenceEquals(left, null) && 
   object.ReferenceEquals(right, null))
    return true;
if(object.ReferenceEquals(left, null))
    return right.Equals(left);
return left.Equals(right);

السبب البسيط هو أن ما يلي سوف يطرح استثناءً:

string a = null;
string b = "foo";

bool equal = a.Equals(b);

وما يلي لن:

string a = null;
string b = "foo";

bool equal = a == b;

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


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

  • الثقافة الحالية
  • الثقافة الحاليةIgnoreCase
  • الثقافة الثابتة
  • InvariantCultureIgnoreCase
  • ترتيبي
  • OrdinalIgnoreCase

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

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

لاحظ أن تعداد مقارنة السلاسل بالإضافة إلى التحميل الزائد لطرق مقارنة السلاسل، وهو موجود منذ .NET 2.0.


طريقة String.CompareTo (سلسلة)

هو في الواقع نوع التنفيذ الآمن لـ طريقة IComparable.CompareTo.التفسير الافتراضي:الثقافة الحالية.

الاستخدام:

تم تصميم أسلوب CompareTo بشكل أساسي للاستخدام في عمليات الفرز أو الترتيب الأبجدي

هكذا

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

طريقة String.Compare

عضو ثابت فئة السلسلة والتي لديها العديد من الأحمال الزائدة.التفسير الافتراضي:الثقافة الحالية.

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

طريقة String.Equals

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

تتضمن أساليب المساواة في فئة String يساوي ثابت, ، ال عامل ثابت ==, ، و ال طريقة المثيل يساوي.


فئة StringComparer

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

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

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

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

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

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

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

أحد الاختلافات الكبيرة التي يجب ملاحظتها هو أن الدالة .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");
  • s1.قارن مع (s2): لا تستخدم إذا كان الغرض الأساسي هو تحديد ما إذا كانت سلسلتان متكافئتان
  • s1 == s2: لا يمكن تجاهل الحالة
  • s1.Equals(s2, StringComparison): يرمي NullReferenceException إذا كان s1 فارغًا
  • String.Equals(s2، StringComparison): من خلال عملية القضاء على هذا ثابتة الطريقة هي الفائز (بافتراض حالة استخدام نموذجية لتحديد ما إذا كانت سلسلتان متكافئتان)!

يعد استخدام .Equals أيضًا أسهل كثيرًا يقرأ.

باستخدام .Equals، يمكنك أيضًا الحصول على خيارات StringComparison.مفيد جدًا لتجاهل الحالة وأشياء أخرى.

راجع للشغل، سيتم تقييم هذا إلى خطأ

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

return a==b

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

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

b = "MYSTRING";

إذن a.Equals(b) خطأ، لكن

a.Equals(b, StringComparison.OrdinalIgnoreCase) 

سيكون صحيحا

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

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top