Runtime: كسر التغيير مع string.IndexOf (سلسلة) من .NET Core 3.0 -> .NET 5.0

تم إنشاؤها على ٢٢ أكتوبر ٢٠٢٠  ·  76تعليقات  ·  مصدر: dotnet/runtime

وصف

أنا أقوم بتوسيع حزمة لدعم .NET 5.0 وواجهت تغييرًا فاصلاً. بالنظر إلى تطبيق وحدة التحكم:

using System;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var actual = "Detail of supported commands\n============\n## Documentation produced for DelegateDecompiler, version 0.28.0 on Thursday, 22 October 2020 16:03\n\r\nThis file documents what linq commands **DelegateDecompiler** supports when\r\nworking with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF).\r\nEF has one of the best implementations for converting Linq `IQueryable<>` commands into database\r\naccess commands, in EF's case T-SQL. Therefore it is a good candidate for using in our tests.\r\n\r\nThis documentation was produced by compaired direct EF Linq queries against the same query implemented\r\nas a DelegateDecompiler's `Computed` properties. This produces a Supported/Not Supported flag\r\non each command type tested. Tests are groups and ordered to try and make finding things\r\neasier.\r\n\r\nSo, if you want to use DelegateDecompiler and are not sure whether the linq command\r\nyou want to use will work then clone this project and write your own tests.\r\n(See [How to add a test](HowToAddMoreTests.md) documentation on how to do this). \r\nIf there is a problem then please fork the repository and add your own tests. \r\nThat will make it much easier to diagnose your issue.\r\n\r\n*Note: The test suite has only recently been set up and has only a handful of tests at the moment.\r\nMore will appear as we move forward.*\r\n\r\n\r\n### Group: Unit Test Group\n#### [My Unit Test1](../TestGroup01UnitTestGroup/Test01MyUnitTest1):\n- Supported\n  * Good1 (line 1)\n  * Good2 (line 2)\n\r\n#### [My Unit Test2](../TestGroup01UnitTestGroup/Test01MyUnitTest2):\n- Supported\n  * Good1 (line 1)\n  * Good2 (line 2)\n\r\n\r\n\nThe End\n";

            var expected = "\n#### [My Unit Test2](";

            Console.WriteLine($"actual.Contains(expected): {actual.Contains(expected)}");
            Console.WriteLine($"actual.IndexOf(expected): {actual.IndexOf(expected)}");
        }
    }
}

أحصل على نتائج مختلفة بناءً على وقت التشغيل من .NET Core 3.0 -> .NET 5.0:

NET Core 3.0:

actual.Contains(expected): True
actual.IndexOf(expected): 1475

NET 5.0:

actual.Contains(expected): True
actual.IndexOf(expected): -1

ترتيب

Windows 10 Pro Build 19041 x64
NET Core 3.1.9
NET 5.0.0-rc.2.20475.5

تراجع؟

نعم ، لقد عملت من خلال .NET Core 3.1.9

area-System.Globalization question

التعليق الأكثر فائدة

tarekgh ، أوافق على أن النتائج المختلفة بين Contains و IndexOf ليست هي المشكلة في حد ذاتها.

من الواضح أن المشكلة تتمثل في IndexOf وهو غير قادر على العثور على سلسلة ASCII واحدة فقط داخل سلسلة ASCII أخرى فقط (لست متأكدًا من وجود أي سلوك يعتمد على اللغة المفروضة على سلاسل ASCII فقط!).

هذا ليس شيئًا أتوقعه من أي تغييرات متعلقة بالإعدادات المحلية / NLS / ICU ؛ في الواقع ، لم أستطع التفكير في أي لغة برمجة أخرى / وقت تشغيل يتصرف هكذا.

إليك حالة اختبار مبسطة ، مكسورة (أعني ، أعطتني نتيجة غير متوقعة تمامًا) على .NET 5 RC 2:

var actual = "\n\r\nTest";
var expected = "\nTest";

Console.WriteLine($"actual.IndexOf(expected): {actual.IndexOf(expected)}"); // => -1

هل يجب أن تعمل بهذه الطريقة؟ ايضا لماذا؟ ما الذي تحاول فعله في الواقع؟

هل كان حقا تغيير مخطط؟

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

أنا آسف ، لكنني لا أعتقد أن هذا كان تغييرًا مخططًا له ، لذلك أود التأكيد: لا يمكنني تخيل أي شخص _ يخطط_ مثل هذا التغيير. مثل ، أعضاء فريق .NET جلسوا معًا وناقشوا:

هل تحتوي السلسلة "\ n \ r \ n" الاختبار "على" \ n اختبار "مع تمكين ICU؟ لا ، من الواضح لا!

ولم يشكو أحد؟ ليست فرصة!

لا يبدو هذا تغييرًا مخططًا أو متوقعًا ، وبدلاً من ذلك يبدو أنه خطأ خطير للغاية ، مانع توافق كبير. لهذا السبب ، لن تعمل تطبيقات .NET الجديدة والمنقولة بشكل صحيح في وقت التشغيل الجديد ، لأنها لن تكون قادرة على العثور على سلاسل فرعية داخل السلسلة!

لماذا تهتم وحدة العناية المركزة بنهايات الخطوط على أي حال؟ هل تحتوي بعض المناطق على نهايات سطور خاصة بها؟

ملاحظة: نعم ، يمكنك أن تجادل بأنه يجب على المرء دائمًا استدعاء بعض المتغيرات المستقلة عن الثقافة IndexOf ، مثل العلم الترتيبي. ولكن ، إذا كنت قد قررت كسرها _that_ الصعب في .NET 5 ، ألا يمكنك جعلها تستخدم فقط الافتراضي السليم والترتيبي بعد ذلك؟ أعتقد أنه سيؤدي إلى كسر تطبيقات أقل من التغيير الحالي الذي نراه في .NET 5 RC 2.

أيضًا ، أعتقد أننا جميعًا نتفهم أنه على الرغم من أن IndexOf يتصرف دائمًا بطريقة خاصة بثقافة معينة ، فهناك _tons_ من التعليمات البرمجية في البرية تستخدم IndexOf بدون العلامات الترتيبية ، وهذا الرمز _ تستخدم للعمل_ (في بعض / معظم الحالات ، على الأقل). وسيتوقف عن العمل بعد تحديث .NET 5.

ال 76 كومينتر

تضمين التغريدة

تمييز المشتركين في هذه المنطقة: safern ،krwq
انظر المعلومات في area-owners.md إذا كنت تريد أن تشترك.

هذا حسب التصميم كما في .NET 5.0 قمنا بالتبديل باستخدام ICU بدلاً من NLS. يمكنك الاطلاع على https://docs.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu للحصول على مزيد من التفاصيل.

لديك خيار استخدام مفتاح التكوين System.Globalization.UseNls للعودة إلى السلوك القديم ولكننا لا نوصي بالقيام بذلك لأن وحدة العناية المركزة هي الأكثر صحة والمضي قدمًا باستخدام وحدة العناية المركزة سيعطي الاتساق عبر أنظمة التشغيل.

نسيت أن تقول ، إذا كنت تريد IndexOf تتصرف مثل Contains ، فيجب عليك استخدام المقارنات الترتيبية في ذلك الوقت.

C# actual.IndexOf(expected, StringComparison.Ordinal)

لديك خيار استخدام مفتاح التكوين System.Globalization.UseNls للعودة إلى السلوك القديم ولكننا لا نوصي بالقيام بذلك لأن وحدة العناية المركزة هي الأكثر صحة والمضي قدمًا باستخدام وحدة العناية المركزة سيعطي الاتساق عبر أنظمة التشغيل.

نعم ، إذا قمت بتشغيل هذا الرمز في Unix باستهداف netcoreapp3.1 فسترى نفس السلوك:

 santifdezm  DESKTOP-1J7TFMI  ~  experimental  indexof  $   /home/santifdezm/experimental/indexof/bin/Debug/netcoreapp3.1/linux-x64/publish/indexof
actual.Contains(expected): True
actual.IndexOf(expected): -1

ومثلtarekgh بمقارنة Ordinal فإنها تُرجع النتيجة المتوقعة.

 santifdezm  DESKTOP-1J7TFMI  ~  experimental  indexof  $  /home/santifdezm/experimental/indexof/bin/Debug/net5.0/linux-x64/publish/indexof
actual.Contains(expected): True
actual.IndexOf(expected): 1475

أعتقد أن هذا فشل لأن مزيج \r\n و \n في سلسلة المصدر. إذا قمت باستبدال كل مثيلات \r\n بـ \n فهذا يعمل. نفس الشيء صحيح إذا صنعت كل شيء \r\n . إنه مجرد مزيج ينتج عنه نتائج مختلفة من مقارنة وحدة العناية المركزة.

كانت المشكلة كما تم الإبلاغ عنها على Twitter هي أنه خلال وقت التشغيل 5.0 ، كانت المكالمات المتكررة للسلسلة. كان مؤشر IndexOf مع نفس المدخلات يعطي نتائج مختلفة في كل مكالمة.

https://twitter.com/jbogard/status/1319381273585061890؟s=21

تحرير: أعلاه كان سوء فهم.

GrabYourPitchforks هل يمكننا تحديث عنوان الإصدار بعد ذلك؟ نظرًا لأن هذا يعد تغييرًا تقنيًا ، ولكن هذا يحدث على نظامي التشغيل Windows و Unix ... أليس كذلك؟

أنا أزعج جيمي دون اتصال للتوضيح. من المحتمل أنني أسأت فهم تقرير المشكلة الأصلي الخاص به. منتديات 280-char ليست فعالة دائمًا في توصيل الأخطاء بشكل واضح. ؛)

فقط للتوضيح ، Contains API تقوم بعملية ترتيبية. IndexOf بدون أي إشارات مقارنة سلاسل عملية لغوية وليست ترتيبية. إذا كنت تريد مقارنة سلوك يحتوي على IndexOf ، فعليك استخدام IndexOf(expected, StringComparison.Ordinal) .
إذا كنت بحاجة إلى معرفة المزيد حول الاختلاف ، فإن https://docs.microsoft.com/en-us/dotnet/csharp/how-to/compare-strings رابط مفيد.

تلقيت توضيحًا على Twitter. التطبيق لا يستدعي IndexOf في حلقة. هذا مجرد تقرير قياسي 3.0 مقابل 5.0 اختلاف سلوكي.

GrabYourPitchforks هل يمكنك مشاركة الرابط https://docs.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu على ردودك على تويتر والإشارة إلى أن لدينا مفتاح تهيئة للعودة إلى السلوك القديم؟

تلقيت توضيحًا على Twitter. التطبيق لا يستدعي IndexOf في حلقة. هذا مجرد تقرير قياسي 3.0 مقابل 5.0 اختلاف سلوكي.

شكرًا ،GrabYourPitchforks ... بناءً على هذا ، أغلقه حسب التصميم.

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

ج #
CultureInfo.CurrentCulture.CompareInfo.IndexOf (الفعلي ، المتوقع ، قارن الخيارات. تجاهل الرموز)


or 

```C#
    actual.IndexOf(expected, StringComparison.Ordinal)

بدلا من

C# actual.IndexOf(expected)

ويجب أن تحصل على السلوك المطلوب.

لا يمكنني رؤية أي شيء عن \r\n مقابل \n في الوثائق المرتبطة بوحدة العناية المركزة (https://docs.microsoft.com/en-us/dotnet/standard/globalization-localization/ العولمة- ICU).

هل كان حقا تغيير مخطط؟

ForNeVeR سيكون من الصعب سرد كل اختلاف فردي بين ICU و NLS. يتحدث المستند عن التغيير الرئيسي للتحول إلى وحدة العناية المركزة. كما أشرت سابقًا ، ليس من الصواب مقارنة نتائج Contains مع IndexOf بدون معلمات StringComparison. لقد أدرجت أعلاه طريقتين يمكنك من خلالها الحصول على السلوك السابق إذا رغبت في ذلك. من التقرير الخاص بهذه المشكلة ، يبدو لي أن استخدام IndexOf يجب أن يستخدم الخيار Ordinal وأنه من الخطأ استخدام المقارنات اللغوية في مثل هذه الحالة. يمكن أن يعتمد استخدام المقارنة اللغوية في مثل هذه الحالة على الثقافة الحالية التي يمكن أن تعطي نتائج مختلفة في بيئات مختلفة.

هل كان حقا تغيير مخطط؟

نعم ، التحول إلى وحدة العناية المركزة هو تغيير مقصود لأسباب مختلفة. يقوم Windows حاليًا بالترويج باستخدام ICU عبر NLS. وحدة العناية المركزة هي المستقبل على أي حال. أيضًا ، ستتيح وحدة العناية المركزة الفرصة للحصول على سلوكيات متسقة عبر أنظمة التشغيل Windows / Linux / OSX أو أي أنظمة أساسية مدعومة. سيعطي استخدام وحدة العناية المركزة الفرصة للتطبيقات لتخصيص سلوك العولمة إذا رغبوا في ذلك.

كما أوضح المستند ، لا يزال لديك خيار العودة إلى السلوك القديم إذا كنت تريد ذلك.

عفوًا ، يقول المستند المشار إليه أن سلوك ICU / NLS على Windows قد يتحول بصمت بناءً على توفر icu.dll في البيئة الفعلية. قد يكون هذا بمثابة مفاجأة كبيرة للتطبيقات المستقلة المنشورة. أتوقع أن يقوم .NET بشحن وحدة العناية المركزة للتغلب على هذه المشكلة إذا تقرر تشغيل المحول ، ولأن وحدة العناية المركزة غير متوفرة في جميع البيئات المستهدفة. هذه التبعية الاختيارية لوقت التشغيل تجعل الأمور أكثر تسلية.

أتوقع أن يقوم .NET بشحن وحدة العناية المركزة للتغلب على هذه المشكلة إذا تقرر تشغيل المحول ، ولأن وحدة العناية المركزة غير متوفرة في جميع البيئات المستهدفة. هذه التبعية الاختيارية لوقت التشغيل تجعل الأمور أكثر تسلية.

يتم الآن نشر وحدة العناية المركزة كحزمة NuGet. يمكن للتطبيقات استخدام هذه الحزم للحصول على التطبيق المستقل لضمان وجود وحدة العناية المركزة. انظر إلى قسم التطبيق المحلي في المستند . باختصار ، يتمتع التطبيق بالتحكم الكامل في السلوك الذي تريد الحصول عليه.

tarekgh ، أوافق على أن النتائج المختلفة بين Contains و IndexOf ليست هي المشكلة في حد ذاتها.

من الواضح أن المشكلة تتمثل في IndexOf وهو غير قادر على العثور على سلسلة ASCII واحدة فقط داخل سلسلة ASCII أخرى فقط (لست متأكدًا من وجود أي سلوك يعتمد على اللغة المفروضة على سلاسل ASCII فقط!).

هذا ليس شيئًا أتوقعه من أي تغييرات متعلقة بالإعدادات المحلية / NLS / ICU ؛ في الواقع ، لم أستطع التفكير في أي لغة برمجة أخرى / وقت تشغيل يتصرف هكذا.

إليك حالة اختبار مبسطة ، مكسورة (أعني ، أعطتني نتيجة غير متوقعة تمامًا) على .NET 5 RC 2:

var actual = "\n\r\nTest";
var expected = "\nTest";

Console.WriteLine($"actual.IndexOf(expected): {actual.IndexOf(expected)}"); // => -1

هل يجب أن تعمل بهذه الطريقة؟ ايضا لماذا؟ ما الذي تحاول فعله في الواقع؟

هل كان حقا تغيير مخطط؟

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

أنا آسف ، لكنني لا أعتقد أن هذا كان تغييرًا مخططًا له ، لذلك أود التأكيد: لا يمكنني تخيل أي شخص _ يخطط_ مثل هذا التغيير. مثل ، أعضاء فريق .NET جلسوا معًا وناقشوا:

هل تحتوي السلسلة "\ n \ r \ n" الاختبار "على" \ n اختبار "مع تمكين ICU؟ لا ، من الواضح لا!

ولم يشكو أحد؟ ليست فرصة!

لا يبدو هذا تغييرًا مخططًا أو متوقعًا ، وبدلاً من ذلك يبدو أنه خطأ خطير للغاية ، مانع توافق كبير. لهذا السبب ، لن تعمل تطبيقات .NET الجديدة والمنقولة بشكل صحيح في وقت التشغيل الجديد ، لأنها لن تكون قادرة على العثور على سلاسل فرعية داخل السلسلة!

لماذا تهتم وحدة العناية المركزة بنهايات الخطوط على أي حال؟ هل تحتوي بعض المناطق على نهايات سطور خاصة بها؟

ملاحظة: نعم ، يمكنك أن تجادل بأنه يجب على المرء دائمًا استدعاء بعض المتغيرات المستقلة عن الثقافة IndexOf ، مثل العلم الترتيبي. ولكن ، إذا كنت قد قررت كسرها _that_ الصعب في .NET 5 ، ألا يمكنك جعلها تستخدم فقط الافتراضي السليم والترتيبي بعد ذلك؟ أعتقد أنه سيؤدي إلى كسر تطبيقات أقل من التغيير الحالي الذي نراه في .NET 5 RC 2.

أيضًا ، أعتقد أننا جميعًا نتفهم أنه على الرغم من أن IndexOf يتصرف دائمًا بطريقة خاصة بثقافة معينة ، فهناك _tons_ من التعليمات البرمجية في البرية تستخدم IndexOf بدون العلامات الترتيبية ، وهذا الرمز _ تستخدم للعمل_ (في بعض / معظم الحالات ، على الأقل). وسيتوقف عن العمل بعد تحديث .NET 5.

تكمن المشكلة بوضوح في عدم قدرة IndexOf على العثور على سلسلة ASCII فقط داخل سلسلة ASCII أخرى فقط (لست متأكدًا من وجود أي سلوك يعتمد على الإعدادات المحلية تم فرضه على سلاسل ASCII فقط!).

ليس صحيحًا أن ASCII مستقل عن الإعدادات المحلية. انظر إلى الرابط http://userguide.icu-project.org/collation/concepts كمثال على كيفية اختلاف سلوك أحرف ASCII باختلاف الثقافات.

For example, in the traditional Spanish sorting order, "ch" is considered a single letter. All words that begin with "ch" sort after all other words beginning with "c", but before words starting with "d".
Other examples of contractions are "ch" in Czech, which sorts after "h", and "lj" and "nj" in Croatian and Latin Serbian, which sort after "l" and "n" respectively.

أريد أيضًا أن أوضح أن وحدة العناية المركزة تختار بياناتها وسلوكها من معيار Unicode الذي يدرسه العديد من الخبراء جيدًا. ستنشرGrabYourPitchforks مزيدًا من التفاصيل حول حالة \r\n\ التي نتحدث عنها هنا. لكن في غضون ذلك ، يمكنك التعرف على المستند https://unicode.org/reports/tr29/ خاصة في الأقسام التي تذكر ما يلي:

Do not break between a CR and LF. Otherwise, break before and after controls.
--
GB3 | CR | × | LF
GB4 | (Control \| CR \| LF) | ÷ |  
GB5 |   | ÷ | (Control \| CR \| LF)

لماذا تهتم وحدة العناية المركزة بنهايات الخطوط على أي حال؟ هل تحتوي بعض المناطق على نهايات سطور خاصة بها؟

تم تناول هذا في الفقرة الأخيرة.

أنا آسف ، لكنني لا أعتقد أن هذا كان تغييرًا مخططًا له ، لذلك أود التأكيد: لا يمكنني تخيل أي شخص يخطط لمثل هذا التغيير. مثل ، أعضاء فريق .NET جلسوا معًا وناقشوا:
لا يبدو هذا تغييرًا مخططًا أو متوقعًا ، وبدلاً من ذلك يبدو أنه خطأ خطير للغاية ، مانع توافق كبير. لهذا السبب ، لن تعمل تطبيقات .NET الجديدة والمنقولة بشكل صحيح في وقت التشغيل الجديد ، لأنها لن تكون قادرة على العثور على سلاسل فرعية داخل السلسلة!

لقد تم التخطيط جيدًا للعمل والتفكير بعمق فيه. يمكنك إلقاء نظرة على المشكلة https://github.com/dotnet/runtime/issues/826 التي نشرناها منذ فترة طويلة وشاركناها علنًا.
أريد التأكيد أيضًا على أن سلوك العولمة يمكن أن يتغير في أي وقت ليس فقط من أجل .NET ولكن لنظام التشغيل والأنظمة الأساسية الأخرى. وهذا أيضًا سبب دعمنا لميزة التطبيق المحلي لوحدة العناية المركزة للسماح للتطبيقات باستخدام إصدار محدد من وحدة العناية المركزة لضمان عدم تغيير السلوك الذي يستخدمونه. شيء آخر ، Windows نفسه يقوم بالترويج باستخدام وحدة العناية المركزة وسيصبح سلوك وحدة العناية المركزة يومًا ما هو ما سيستخدمه غالبية المستخدمين.

كما هو الحال مع العلم الترتيبي. ولكن ، إذا كنت قد قررت كسرها بهذه الصعوبة في .NET 5 ، ألا يمكنك أن تجعلها تستخدم فقط الافتراضي السليم والترتيبي بعد ذلك؟ أعتقد أنه سيؤدي إلى كسر تطبيقات أقل من التغيير الحالي الذي نراه في .NET 5 RC 2.

في الواقع لقد حاولنا من قبل أن نجعل السلوك الترتيبي هو السلوك الافتراضي من قبل أثناء إصدارات Silverlight والذي تسبب في مشاكل أكثر بكثير مما تم الإبلاغ عنه هنا. نحن نبحث عن المزيد من الطرق لمساعدة المطورين على أن يكونوا واعين عند استدعاء شيء مثل IndexOf وأن نقدم عن قصد إشارات StringComparison للتعبير عن النية. نرحب بأي أفكار قد تأتي بها أيضًا.

أيضًا ، أعتقد أننا جميعًا نفهم أنه على الرغم من أن IndexO تتصرف دائمًا بطريقة خاصة بالثقافة ، فهناك الكثير من التعليمات البرمجية في البرية التي تستخدم IndexOf بدون العلامات الترتيبية ، وهذا الرمز يستخدم للعمل (في بعض / معظم الحالات ، على الأقل). وسيتوقف عن العمل بعد تحديث .NET 5.

هذا هو السبب في أننا نقدم مفتاح تكوين للعودة إلى السلوك القديم إذا كنت ترغب في ذلك أيضًا. انظر إلى System.Globalization.UseNls

tarekgh ، شكرا على الشرح الشامل!

في الوقت الحالي ، أعتقد أنه من الأفضل بالنسبة لي أن أنتظر تفاصيل حول سلوك \r\n المحدد. ليس من الواضح بالنسبة لي كيف يستخدم IndexOf "قواعد حدود مجموعة حروف الكتابة" (وما إذا كان ينبغي القيام بذلك) عند إجراء هذا البحث تحديدًا).

أيضًا ، حتى إذا كانت مواصفات Unicode ذات صلة هنا (والتي قد تكون جيدة جدًا!) ، من قراءة https://unicode.org/reports/tr29/ ، لست متأكدًا من أنها تمنع مطابقة آخر \n . عندما أقرأ المواصفات ، تقول CR | × | LF ، حيث × تعني "بلا حدود (لا تسمح بالفاصل هنا)". لذلك ، عند كسر تسلسل \r\n\n ، فإنه يمنع فقط وضع "الفاصل" بين الحرف الأول والثاني ، ولكن لا بأس من وضع "الفاصل" قبل الحرف الثالث ، أليس كذلك؟ لذا ، قرأت \r\n\n كمجموعتين منفصلتين من "مجموعات حروف اللغة" ، وحتى إذا كان يجب أن يتطابق IndexOf فقط مع مجموعات حروف اللغة الكاملة ولم أتطرق أبدًا إلى أجزاء من المجموعات ، فلا يزال يتعين العثور على سلسلة فرعية \nTest داخل السلسلة \n\r\nTest .

أيضًا ، هل تخبرنا أن أوقات التشغيل / لغات البرمجة الأخرى التي تعتمد على ICU و / أو مواصفات Unicode يجب أن تتصرف بنفس الطريقة المكتوبة في هذا المثال المحدد؟

نحن نبحث عن المزيد من الطرق لمساعدة المطورين على أن يكونوا واعين عند استدعاء شيء مثل IndexOf وأن نقدم عن قصد إشارات StringComparison للتعبير عن النية. نرحب بأي أفكار قد تأتي بها أيضًا.

_ ( إخلاء مسؤولية ضروري: أنا أعمل لدى JetBrains في عدة مشاريع ، بما في ذلك ReSharper.) _

لم أرغب في البداية في طرح هذه النقطة هنا حتى لا أبدو كإعلان ، لكنني أعتقد أن هذا وثيق الصلة جدًا ، لذا سأضطر إلى القيام بذلك. سيعرض ReSharper افتراضيًا التحذير التالي لرمز المستخدم الذي يستدعي IndexOf :
image

_ (يرجى ملاحظة أنني لم أكن على علم بهذا التشخيص ReSharper بالتحديد قبل التورط في هذا الموضوع ، لذلك أنا لا أشارك هنا فقط لتقديم هذه الحجة) _

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

تضمين التغريدة

أيضًا ، حتى إذا كانت مواصفات Unicode ذات صلة هنا (والتي قد تكون جيدة جدًا!) ، من قراءة unicode.org/reports/tr29 ، لست متأكدًا من أنها تمنع مطابقة ذلك الأخير \ n. أثناء قراءة المواصفات ، تقول CR | × | LF ، حيث × تعني "بلا حدود (لا تسمح بالفاصل هنا)". لذلك ، عند كسر تسلسل \ r \ n \ n ، فإنه يمنع فقط وضع "الفاصل" بين الحرف الأول والثاني ، ولكن لا بأس من وضع "الفاصل" قبل الحرف الثالث ، أليس كذلك؟ لذلك ، قرأت \ r \ n \ n على شكل "مجموعتين منفصلتين من حروف الحروف"

هذا صحيح. \r\n\n مجموعتين مثل \r\n و \n .

وحتى إذا كان على IndexOf أن يتطابق فقط مع مجموعات حروف اللغة الكاملة ولا يلمس أبدًا أجزاء من الكتل ، فلا يزال يتعين عليه العثور على سلسلة فرعية \ n اختبار داخل السلسلة \ n \ r \ n الاختبار.

هذا غير صحيح. سيتم تقسيم \n\r\nTest إلى أجزاء. \n و \r\n و Test . من الواضح أن \nTest لا يمكن أن يكون جزءًا من هذه السلسلة. فكر في استبدال الكتلة \r\n ببعض الرموز X . الآن ستكون سلسلة المصدر \nXTest ولا تحتوي على \nTest .

أيضًا ، هل تخبرنا أن أوقات التشغيل / لغات البرمجة الأخرى التي تعتمد على ICU و / أو مواصفات Unicode يجب أن تتصرف بنفس الطريقة المكتوبة في هذا المثال المحدد؟

في حالة استخدام مستوى قوة التجميع الافتراضي ، فإن الإجابة هي نعم. يمكن أن تسمح وحدة العناية المركزة بتغيير مستوى القوة مما قد يؤثر على النتيجة. على سبيل المثال ، كما ذكرت سابقًا ، افعل شيئًا مثل:

CultureInfo.CurrentCulture.CompareInfo.IndexOf(actual, expected, CompareOptions.IgnoreSymbols)

سيغير مستوى القوة وسيجعل العملية تتجاهل الرموز (والتي ستغير سلوك \n و \r حيث سيتم تجاهلها في ذلك الوقت)

أيضًا ، لقد كتبت تطبيق C الأصلي النقي لوحدة العناية المركزة وشغلت نفس الحالة:

void SearchString(const char *target, int32_t targetLength, const char *source, int32_t sourceLength)
{
    static UChar usource[100];
    static UChar utarget[100];

    u_charsToUChars(source, usource, sourceLength);
    u_charsToUChars(target, utarget, targetLength);

    UErrorCode status = U_ZERO_ERROR;
    UStringSearch* pSearcher = usearch_open(utarget, targetLength, usource, sourceLength, "en_US", nullptr, &status);
    if (!U_SUCCESS(status))
    {
        printf("usearch_open failed with %d\n", status);
        return;
    }

    int32_t index = usearch_next(pSearcher, &status);
    if (!U_SUCCESS(status))
    {
        printf("usearch_next failed with %d\n", status);
        return;
    }

    printf("search result = %d\n", index);
    usearch_close(pSearcher);
}


int main()
{
    SearchString("\nT", 2, "\r\nT", 3);
    SearchString("\nT", 2, "\n\nT", 3);
}

سيخرج هذا التطبيق النتائج:

search result = -1
search result = 1

وهو ما يماثل السلوك الذي تراه مع .NET.

في الوقت الحالي ، أعتقد أنه من الأفضل بالنسبة لي انتظار تفاصيل حول هذا \ r \ n السلوك المحدد. ليس من الواضح بالنسبة لي كيف يستخدم IndexOf "قواعد حدود مجموعة حروف اللغة" (وما إذا كان ينبغي القيام بذلك) عند إجراء هذا البحث تحديدًا).

من المؤكد أن المجموعات تؤثر على عملية الترتيب. إذا نظرت إلى http://unicode.org/reports/tr29/tr29-7.html ، فإنه ينص بوضوح على ما يلي:

Grapheme clusters include, but are not limited to, combining character sequences such as (g + °), digraphs such as Slovak “ch”, and sequences with letter modifiers such as kw. تعد حدود مجموعة حروف العطف مهمة لعملية التجميع , regular-expressions, and counting “character” positions within text. Word boundaries, line boundaries and sentence boundaries do not occur within a grapheme cluster. In this section, the Unicode Standard provides a determination of where the default grapheme boundaries fall in a string of characters. This algorithm can be tailored for specific locales or other customizations, which is what is done in providing contracting characters in collation tailoring tables.

لست متأكدًا مما إذا كان سيكون هناك المزيد من التفاصيل ، لكنني سأدعGrabYourPitchforks يعلق إذا كان لديه المزيد

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

شكر!
هذا هو نفس الاتجاه الذي نفكر فيه أيضًا.

من أجل مصلحي ، قارنت بين الأحمال الزائدة المختلفة بين الإصدارات:

| الطريقة | netcoreapp3.1 | net5.0 |
| ------------------------------------------------- --------------- | ----------------- | ---------- |
| actual.Contains(expected) | صحيح | صحيح |
| actual.IndexOf(expected) | 1475 | -1 |
| actual.Contains(expected, StringComparison.CurrentCulture) | صحيح | خطأ |
| actual.IndexOf(expected, StringComparison.CurrentCulture) | 1475 | -1 |
| actual.Contains(expected, StringComparison.Ordinal) | صحيح | صحيح |
| actual.IndexOf(expected, StringComparison.Ordinal) | 1475 | 1475 |
| actual.Contains(expected, StringComparison.InvariantCulture) | صحيح | خطأ |
| actual.IndexOf(expected, StringComparison.InvariantCulture) | 1475 | -1 |

يرجى تضمين محلل لهذا الغرض.

يبدو هذا كواحد من تلك التغييرات التي ، على الرغم من أنها جيدة على المدى الطويل ، في حين أنها تخلق قدرًا هائلاً من التغيير بمجرد إطلاق .NET 5. لذلك ، إذا كان سلوك هذه الطرق يختلف بين .NET 5 و .NET Core 3.1 ، فما الذي سيحدث عندما يستدعي .NET 5 كائنًا محددًا داخل مكتبة .NET Standard 2.0 تتعامل مع string تم تمريره إليه من موقع الاتصال .NET؟ هل يعتاد السلوك القديم أم السلوك الجديد؟

Aaronontheweb سلوك جديد. لقد رأيت هذا في البداية من تأكيد في NUnit3 ، والذي يستهدف netstandard2.0 . بعد الترقية ، بدأ اختباري بالفشل عندما قمت فقط بتغيير إطار العمل الهدف.

هذا ليس رائعًا - لا يمكنني التحكم في ما تفعله المكتبات القديمة التي أشير إليها إذا كنت أرغب في الترقية.

كم عدد التطبيقات التي لن تكتشف ذلك في اختبارات الوحدة وتضع ذلك في الإنتاج؟
هل نظر فريق .NET في الألم والمشكلات والتكلفة التي قد يسببها ذلك؟

هذا ليس رائعًا - لا يمكنني التحكم في ما تفعله المكتبات القديمة التي أشير إليها إذا كنت أرغب في الترقية.

فخ جميل!
إضاعة الوقت السعيد عن طريق صيد الحشرات الغريبة 🎉
ولكن لماذا لا تساعد InvariantGlobalization في حل هذه المشكلة؟

يرجى تضمين محلل لهذا الغرض.

بلى. ولا تنس دعم F #.

كم عدد التطبيقات التي لن تكتشف ذلك في اختبارات الوحدة

صفر - نظرًا لأن اختبارات الوحدة لا تهدف إلى اختبار libs / أطر العمل الخارجية مثل .NET BCL نفسه.

رأيي هو أنه يجب أن تكون هناك سمة على مستوى التجميع يمكنها التحكم في نمط تغيير السلوك هذا. بعد ذلك على الأقل ، يمكنك الاشتراك / إلغاء الاشتراك على مستوى كل مجموعة. هذا يعني إذن أن مشكلة .NET Standard تختفي أيضًا.

هذا ليس رائعًا - لا يمكنني التحكم في ما تفعله المكتبات القديمة التي أشير إليها إذا كنت أرغب في الترقية.

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

لا يمكنك الاعتماد على بيانات العولمة التي تظل مستقرة بمرور الوقت. خذها من فريق Windows أنهم لا يخشون كسر الأشخاص الذين يعتمدون على بيانات العولمة المستقرة. يجب أن تكون وظائف العولمة صندوقًا أسود ؛ لا أعتقد أنه من المنطقي بالنسبة للمكتبات (خاصة تلك التي تستهدف .NET Standard) أن تقول إنها تعتمد على تفاصيل التنفيذ مثل هذه.

أنا متأكد من أن الكثير من الناس قد اشتكوا من وظائف عولمة .NET التي تعيد نتائج مختلفة على Windows مقابل Linux (وربما حتى المزيد من الناس لم يلاحظوا ذلك حتى الآن). من الأفضل توحيد السلوك بين Windows والأنظمة الأساسية الأخرى ، وأي رمز صحيح يجب ألا يعتمد على بيانات العولمة التي لا يمكن تغييرها ، بغض النظر.

هل تفكر في إجراء تغيير فاصل لجعل StringComparison.Ordinal استراتيجية المقارنة الافتراضية؟ نظرًا لأن العولمة غير مستقرة للغاية ، فمن المنطقي أن يستخدم التنفيذ الافتراضي على الأقل خوارزمية مستقرة بدلاً من ذلك. أنا على استعداد للمراهنة على أن 99.9٪ من الأشخاص الذين يستخدمون string.Equals(...) أو string.Contains(...) وما إلى ذلك دون تجاوز StringComparison لا يفعلون ذلك بنية صريحة للتعامل مع المراوغات الغريبة المتعلقة المواقع.

تحرير: أعتقد أن سؤالي قد تمت الإجابة عليه بالفعل:

في الواقع لقد حاولنا من قبل أن نجعل السلوك الترتيبي هو السلوك الافتراضي من قبل أثناء إصدارات Silverlight والذي تسبب في مشاكل أكثر بكثير مما تم الإبلاغ عنه هنا. نحن نبحث عن المزيد من الطرق لمساعدة المطورين على أن يكونوا واعين عند استدعاء شيء مثل IndexOf وأن نقدم عن قصد إشارات StringComparison للتعبير عن النية. نرحب بأي أفكار قد تأتي بها أيضًا.

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

أنا أصنع مكتبات لقمة العيش وليس تطبيقات. أنا أفضل أن يكون لدي طريقة وقت التجميع للتعامل مع هذا.

معظم العمل الذي نقوم به هو InvariantCulture ، والذي من المفترض حسب فهمي السابق أن يكون غير قابل للتغيير حسب التصميم. يبدو أن سلوك IndexOf يختلف أيضًا بين .NET 5.0 و .NET Core 3.1 في ظل هذه الظروف أيضًا.

كيف يمكن لأي محلل أن يساعد في المشاريع القائمة؟

petarrepac هذا أيضًا شيء C # فقط.

isaacabraham و VB أيضًا ؛)

أنا أفضل أن يكون لدي طريقة وقت التجميع للتعامل مع هذا.

Aaronontheweb لديك طريقة وقت التجميع للتعامل مع هذا (عند تجميع التطبيقات). يمكنك إضافة هذا إلى مشروعك:

<ItemGroup>
  <RuntimeHostConfigurationOption Include="System.Globalization.UseNls" Value="true" />
</ItemGroup>

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

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

ما الذي سيحدث عندما يستدعي .NET 5 كائنًا محددًا داخل مكتبة .NET Standard 2.0 التي تتعامل مع سلسلة تم تمريرها إليها من موقع الاستدعاء .NET؟ هل يعتاد السلوك القديم أم السلوك الجديد؟

سيتم استخدام السلوك الجديد ، لأنه يعتمد على وقت التشغيل ويكون .NET Standard مجرد معيار لأوقات التشغيل ليتم تنفيذه. ومع ذلك ، لاحظ أن هذا يؤدي إلى تناسق النظام الأساسي بين نظامي التشغيل Unix و Windows ، إذا قمت بتشغيل نفس المكتبات التي يساور الأشخاص مخاوف بشأنها في Unix ، فستحصل على نتيجة ICU حيث أن ICU هو الدعم مكتبة في يونكس.

reflectronic محق في جميع نقاطه https://github.com/dotnet/runtime/issues/43736#issuecomment -716681586.

للتعليق على نتائج jbogard المذكورة هنا https://github.com/dotnet/runtime/issues/43736#issuecomment -716527590 ، يمكنك فقط تلخيص النتائج من خلال مقارنة السلوك اللغوي بين Windows و ICU. بالمناسبة ، تستخدم ICU الآن من قبل العديد من التطبيقات على Windows ومن المتوقع أن يزداد الاستخدام. أيضًا ، هذه النتائج لا تشمل Linux مع .NET Core 3.1 والإصدارات الأقدم. والتي ستظهر التناسق بين .NET 5.0 والإصدارات السابقة على Linux.

سيتم كسر النقطة المتعلقة بالمكتبة التي كانت تعمل في السابق ، وهذا ليس صحيحًا تمامًا لأن مثل هذه المكتبات كانت معطلة بالفعل على Linux.

هل تفكر في إجراء تغيير فاصل لجعل StringComparison.Ordinal استراتيجية المقارنة الافتراضية؟

لقد ذكرت سابقًا أننا جربنا ذلك من قبل ولكن حجم الشكاوى كان كبيرًا جدًا لدرجة أننا لم نتمكن من تطبيقها. نحن نبحث في طرق لمساعدة المطورين على أن يكونوا واعين عند تحديد علامات مقارنة السلسلة عند استدعاء واجهات برمجة تطبيقات التجميع.

أنا أصنع مكتبات لقمة العيش وليس تطبيقات. أنا أفضل أن يكون لدي طريقة وقت التجميع للتعامل مع هذا.

نعم ، يمكن لبعض المحلل المساعدة في مثل هذه الحالة. عادةً ما تنظر إلى مكالمات APIs الخاصة بالترتيب وتبحث عن أي منها لا يُظهر نية استخدام العملية الترتيبية أو اللغوية.

كيف يمكن لأي محلل أن يساعد في المشاريع القائمة؟

تقوم المحللون بفحص الكود واكتشاف استدعاءات واجهات برمجة التطبيقات (APIs) للترتيب التي لا تمرر العلامات من شأنها أن تساعد في النظر إلى مثل هذه المكالمات وإصلاحها إذا تم اكتشاف مشكلة.

هذا أيضًا شيء C # فقط.

التغيير داخل وقت تشغيل .NET الذي يجب أن يكون عموميًا وليس مقيدًا بـ C #.

tarekgh كيف يظهر محلل C # نفسه في قاعدة كود VB أو F #؟

معظم العمل الذي نقوم به هو InvariantCulture ، والذي من المفترض حسب فهمي السابق أن يكون غير قابل للتغيير حسب التصميم.

بشكل حاسم ، قبل هذا التغيير ، كان من المستحيل الاعتماد فعليًا على هذا الرمز عبر الأنظمة الأساسية ؛ ما يتصرف به كل من NLS و ICU ، حتى عند استخدام الثقافة الثابتة ، ليسا دائمًا نفس الشيء (كما يتضح من هذه المشكلة). مثل tarekgh قال ، كان هذا الرمز يعمل بشكل مختلف على Linux طوال الوقت. الآن وقد تم إجراء هذا التغيير ، لأي تثبيت حديث لـ Windows ، يجب أن يكون ما تعنيه "الثقافة الثابتة" - في الواقع - متسقًا على جميع الأنظمة الأساسية.

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

أنا لست متحمسًا لاحتمال تقديم .NET 5 لمجموعة جديدة من العناصر المجهولة وإعادة النظر في تلك الإصلاحات ليس فقط لمكتباتي ، ولكن أيضًا تبعياتنا النهائية. هذه تكلفة اقتصادية كبيرة علينا ولا تؤدي إلى تحسينات إنتاجية جديدة لمستخدمينا. يجب على شخص ما في MSFT إعطاء بعض الاعتبار في مناقشة التكاليف / الفوائد لإجراء هذا التغيير.

تحرير: مثل ، حصلت على المزايا التقنية بالفعل - نعم ، شكرًا لك. الرجاء المساعدة في بيع الفوائد الاقتصادية غير الواضحة لإجراء هذا التغيير بدلاً من التكاليف. لماذا يجب على المستخدمين اتخاذ قفزة والترقية إلى .NET 5 على أي حال بالنظر إلى ما يبدو أن هذه المشكلة هي عش الفئران؟

tarekgh كيف يظهر محلل C # نفسه في قاعدة كود VB أو F #؟

يمكننا تغطية C # و VB بمحلل واحد (نحن نسعى جاهدين لجعل محللينا حياديين للغة حيثما أمكن ذلك) ، لكن لا يمكننا الحصول على تغطية محلل لـ F # في هذا الوقت.

Aaronontheweb ، أي شخص يستخدم الوظيفة الثقافية ويفترض أنه لن يتغير ، فقد تم كسره بالفعل حتى لو لم نقم بتغييرات وحدة العناية المركزة هذه. انظر إلى المدونة https://docs.microsoft.com/en-us/archive/blogs/shawnste/locale-culture-data-churn من فريق Windows الذي يخبرنا حتى أن سلوك NLS يتغير من أجل التحسينات أيضًا. لذا ، فإن المشكلة هنا لا تتعلق بالانتقال إلى وحدة العناية المركزة أكثر من مجرد اكتشاف أي افتراضات خاطئة من منظور التطبيقات / المكتبات. الترقية إلى 5.0 مماثلة للترقية إلى الإصدارات السابقة الأخرى. ستحصل التطبيقات على الكثير من الميزات الرائعة الجديدة والتطبيقات التي تحتاج إلى اختبار حيث قد تكون هناك بعض التغييرات العاجلة بين الإصدارات. أنا لا أفكر في تغيير سلوك العولمة حقًا لأننا نقول دائمًا أن العولمة يمكن أن تتغير في أي وقت بين إصدارات نظام التشغيل ونظام التشغيل. كما هو موضح من قبل ، لدينا مفتاح التكوين لاختيار الترقية إلى 5.0 مع الاستمرار في استخدام NLS. من شأنها أن تجعل وحدة العناية المركزة ليست بالفعل عاملاً في قرار الترقية. الآن مع وحدة العناية المركزة ، ستتاح للتطبيقات فرصة الحصول على مزيد من الاتساق عبر أنظمة التشغيل وحتى يمكن أن يكون لها مزيد من التحكم في سلوك العولمة إذا قررت استخدام وحدة العناية المركزة المحلية للتطبيق نحن نقدم المزيد من التحكم في التطبيقات أكثر من ذي قبل.

ذات صلة: https://github.com/dotnet/runtime/issues/43802

(وهذا الموضوع لا تتبع IndexOf _per se_، بل يناقش العواقب غير المقصودة من و Compare روتين المتعثرين لالمقارن ثقافة علم.)

كيف يمكن لأي محلل أن يساعد في المشاريع القائمة؟

تقوم المحللون بفحص الكود واكتشاف استدعاءات واجهات برمجة التطبيقات (APIs) للترتيب التي لا تمرر العلامات من شأنها أن تساعد في النظر إلى مثل هذه المكالمات وإصلاحها إذا تم اكتشاف مشكلة.

أعتقد أنه يجب إضافة أدوات التحليل إلى csproj.
هذا لن يحدث تلقائيا. لذلك ، سيتم نقل الكثير من المشاريع الحالية إلى .NET 5 بدون أدوات التحليل هذه.
بالإضافة إلى ذلك ، كما ذكرنا سابقًا ، لن يساعد ذلك في مشاريع F #.

jeffhandley شكرا لك ، هذا يؤكد ما فهمته بالفعل. لذلك ، من المهم الاعتراف بأن "الحل البديل" المحتمل لن يساعد مستخدمي F # (سوق صغير ولكنه مع ذلك مدعوم بالكامل من MS كمواطن من الدرجة الأولى لـ .NET). ليس لدي أي فكرة عما يعنيه هذا:

التغيير داخل وقت تشغيل .NET الذي يجب أن يكون عموميًا وليس مقيدًا بـ C #.

ليس لدي أي فكرة عما يعنيه هذا:
التغيير داخل وقت تشغيل .NET الذي يجب أن يكون عموميًا وليس مقيدًا بـ C #.

قصدت أن أي لغة تستخدم وقت تشغيل .NET ستتأثر وليس فقط C #.

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

أفهم تمامًا المزايا التقنية للقيام بذلك ولا أقترح عدم إجراء تغيير (على المدى الطويل يبدو أن هذه هي الخطوة الصحيحة). كما أنني لا أقول أنه لم يتم توثيقها بالفعل كأفضل ممارسة. ما أقوله هو أننا نحتاج حقًا إلى أن يكون هذا خطأً كبيرًا أحمر وامضًا للمطورين الذين يحاولون رفع مستوى .NET 5. خارج الصندوق سيفترض المطورون أن هذا "يعمل فقط" بخلاف ذلك.

في الوقت الحالي ، يمكنك استخدام مكتبة محلل Roslyn من https://github.com/meziantou/Meziantou.Analyzer/tree/master/docs.

في هذه الحالة بالذات ، سيؤدي هذا إلى MA0074 - تجنب الأساليب الضمنية الحساسة للثقافة

image

بعد قولي هذا ، يجب أن يكون هذا خارج الصندوق بالفعل ، لقد فتحت قضية Roslyn هذه هنا: https://github.com/dotnet/roslyn-analyzers/issues/4367

tarekgh شكرا

نحن نبحث عن المزيد من الطرق لمساعدة المطورين على أن يكونوا واعين عند استدعاء شيء مثل IndexOf وأن نقدم عن قصد إشارات StringComparison للتعبير عن النية. نرحب بأي أفكار قد تأتي بها أيضًا.

ماذا عن إهمال الطرق القديمة (باستخدام السمة [Obsolete]

ماذا يحدث للتوافق القياسي مع .NET عندما يكون سطح API هو نفسه ولكن يتغير السلوك؟

لا يزعجني أي تغيير لتكريم مجموعات حروف اللغة طالما أن التأثير موثق جيدًا. التغيير الذي يتسبب في أن يتصرف أفراد عائلة أساليب السلسلة بشكل غير متسق من بعضهم البعض.

الشخص الذي يقوم بالتدوين غير الرسمي للأوتار ، غير مبالٍ بغموض الأحرف ، أو مجموعات حروف الكتابة ، أو اللغة المحلية ، سيأخذ ذلك على أنه إذا نجح str. يحتوي (أيًا كان) ، فلا داعي لفحص النتيجة من str. IndexOf (أيا كان) ) لأنه قيل لنا للتو إنه موجود وبالتالي يمكن العثور عليه. لا يهم أي المعلمة الثانية التي لا يهتمون بمعرفتها هي المعلمة الافتراضية لأن التقصير من المؤكد أنه سيتصرف بنفس الطريقة عبر الأساليب ، مما يحررهم من الحاجة إلى دراسة جميع التفاصيل الدقيقة لاستخدامها على الإطلاق.

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

أنا أتفق معlupestro. التناقض في سلوك الأسلوب مقلق للغاية. إذا كان لديك أساليب طويلة الأمد تتصرف بشكل مختلف وغير متسق ، فسيكون هناك الكثير من الحزن. سيواجه الناس هذا الأمر ، وسيشعرون بالخيانة من قبل API ومن ثم سوف يتساءلون عن القنابل الزمنية الأخرى التي تنتظر انفجارها. قد يكون العديد ممن يتبنوا .NET سيكتبون C # على هذا النوع من القضايا. يبدو أنه يجب عليك إما إزالة التحميل الزائد الذي لا يقبل الإعدادات المحلية أو تسوية الإعدادات المحلية الافتراضية للطرق. يوجد بالفعل مقارنة ومقارنة عامة ، ربما يلزم فهرس (آخر) فهرس (أي) و (آخر) فهرس (أي) ترتيبي. لا أحب هذا الحل ولكن على الأقل سيكون متوافقًا مع ما هو موجود حاليًا. ربما يجب إهمال فكرة الاستخدام الترتيبي في السلسلة. إذا اضطررت للاختيار بين سريع أو صحيح ، فسأختار "الصحيح" في كل مرة. السلوكيات غير المتسقة وغير البديهية محبطة للغاية.

أرى أن هذه المشكلة قد تم إغلاقها بالفعل ، لذا أفترض أنه قد تقرر بالفعل المضي قدمًا في .NET 5.0. أعلم أن هذه الأشياء صعبة وأن معلومات الثقافة (مثل الوقت) يمكن أن تتغير لجميع أنواع الأسباب غير الفنية. يحتاج المطورون إلى أن يكونوا على دراية بهذا ، لكنهم يحتاجون أيضًا إلى الاعتماد على واجهات برمجة التطبيقات الخاصة بهم ليكونوا متسقين ذاتيًا. يجب أن يكون هناك تحذير على الأقل (في الإصدار 5.0) كما أشار

TLDR: قم بتغيير الأشياء التي تحتاج إلى تغيير ولكن لا تجعل واجهة برمجة التطبيقات غير متسقة للقيام بذلك. إذا كنت ستكسرها ، استبدله بشيء أفضل.

لقد كنت أستخدم .NET لسنوات ودائمًا ما أستخدم InvariantCulture عند استخدام هذه الوظائف. فيما يتعلق باللغات الأخرى غير الإنجليزية ، كنت دائمًا على دراية بأزواج الأحرف التي تعمل كأسماء مستعارة لأحرف أخرى خاصة بلغة معينة ، والعمل الإضافي الذي يتم إجراؤه للتحقق من هذه الأزواج عند إجراء مقارنات مع CurrentCulture باعتباره الخيار الافتراضي. لقد أذهلني هذا ، على سبيل المثال ، عند كتابة كود ASP.NET الذي يضبط CurrentCulture في مؤشر الترابط استنادًا إلى اللغة المفضلة للمستخدم التي يرسلها المستعرض ، والمقارنات بين المستخدم الذي لا يستخدم اللغة الإنجليزية تجعل الكود ينكسر بطرق خفية ، خاصة عندما تحتوي السلاسل على مزيج من نص أدخله المستخدم (لغوي) ونص ترتيبي.

يعد سلوك مجموعة Unicode grapheme هذا سلوكًا جديدًا بالنسبة لي ، حيث كنت أتوقع سلوكًا ترتيبيًا لتغذية الأسطر وعودة السطر ، حتى لو كنت قد استخدمت الحمل الزائد الثابت كما أفعل عادةً. يبدو لي أن السلوك الذي يقوم بمزيد من العمل ويتطلب معرفة متخصصة يجب أن يكون سلوكًا اختياريًا ، بغض النظر عن الصواب التقني. ربما أبحرت تلك السفينة منذ فترة طويلة ، ولكن يجب إجراء هذا التغيير المفاجئ بشفافية ، مثل تغيير اللغة ، على سبيل المثال ، دون الحاجة إلى قراءة مدونة غامضة. بالكاد يدرك زملائي ميزات C # 9.0 الجديدة ، ناهيك عن بعض قواعد وحدة العناية المركزة الغامضة التي قد تؤثر على الكود الذي يكتبونه اليوم والذي قد يتم نقله في يوم من الأيام إلى .NET 5 (أو ، على الأرجح ، .NET 6 أو 7).

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

تم نشر المسودة على https://github.com/dotnet/runtime/issues/43956. يسرد العديد من البدائل للمسارات المحتملة إلى الأمام (بما في ذلك عدم القيام بأي شيء) ويوازن بين إيجابيات وسلبيات كل نهج. لا تتردد في ترك أي ملاحظات حول مسارات العمل المقترحة هناك.

إذا كنت تبلغ عن خطأ ، فالرجاء إرسال مشكلة جديدة واستخدام هذه المشكلة الجديدة لوصف الخطأ.

إذا كانت لديك تعليقات على هذه المشكلة بالذات ( "\r\n" مقابل "\n" ) ، يرجى الاستمرار في الرد في هذا الموضوع. شكر!

إعادة الفتح بينما نفكر في الأساليب الموضحة في مستندGrabYourPitchforks .

نسمعك - هناك الكثير من التعليقات الواضحة هنا - نحن نعمل على اكتشاف الطريق الصحيح للمضي قدمًا ، وسنواصل تحديث هذه المشكلة.

لا يزعجني أي تغيير لتكريم مجموعات حروف اللغة طالما أن التأثير موثق جيدًا. التغيير الذي يتسبب في أن يتصرف أفراد عائلة أساليب السلسلة بشكل غير متسق من بعضهم البعض.

الشخص الذي يقوم بالتدوين غير الرسمي للأوتار ، غير مبالٍ بغموض الأحرف ، أو مجموعات حروف الكتابة ، أو اللغة المحلية ، سيأخذ ذلك على أنه إذا نجح str. يحتوي (أيًا كان) ، فلا داعي لفحص النتيجة من str. IndexOf (أيا كان) ) لأنه قيل لنا للتو إنه موجود وبالتالي يمكن العثور عليه. لا يهم أي المعلمة الثانية التي لا يهتمون بمعرفتها هي المعلمة الافتراضية لأن التقصير من المؤكد أنه يتصرف _نفس الطرق_ ، مما يحررهم من الحاجة إلى دراسة جميع التفاصيل الدقيقة لاستخدامها على الإطلاق.

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

نعم ، هذا عبّر تمامًا عن مخاوفي. بصفتنا مطورًا صينيًا نموذجيًا ، نادرًا ما نضع StringComparison أو CultureInfo صراحة عند استدعاء الأساليب ذات الصلة بالسلسلة في أكواد التطبيق لدينا ، وهي تعمل فقط. نحن بالتأكيد لا نتوقع سلوكًا مختلفًا بين IndexOf و Contains !
.net 5.0
image
.net الأساسية 3.1
image
.الإطار الصافي
image

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

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

إذا كنت أتابع الأشياء بشكل صحيح ، فقد استخدم IndexOf دائمًا المقارنة الترتيبية ، فقد استخدم دائمًا مقارنة الثقافة الحالية. يضيف .NET 5.0 الممنوح مزيدًا من التناقض. لكن الخطأ هنا كان في تصميم واجهة برمجة التطبيقات الأصلي الذي سمح بهذا التناقض.

هذا صحيح ولكن العكس هو الصحيح ، يستخدم IndexOf(string) الثقافة الحالية ، ويستخدم IndexOf(char) الترتيب الترتيبي و Contains يستخدم الترتيب الترتيبي.

سأشرح بإيجاز الاختلافات بين IndexOf مقابل Contains التي ألمح إليها الآخرون مؤخرًا.

افترض IndexOf(string) دائمًا مقارنة _CurrentCulture_ ، و Contains(string) افترض دائمًا مقارنة _Orinal_. كان هذا التناقض موجودًا في .NET Framework. إنه ليس تناقضًا جديدًا تم تقديمه في .NET 5. على سبيل المثال ، في .NET Framework (الذي يستخدم مرفق NLS الخاص بـ Windows) ، يقارن الرابط "æ" والسلسلة المكونة من حرفين "ae" على أنها متساوية في المقارنة اللغوية. ينتج عن هذا التناقض التالي:

// Sample on .NET Framework, showing Contains & IndexOf returning inconsistent results
Console.WriteLine("encyclopædia".Contains("ae")); // prints 'False'
Console.WriteLine("encyclopædie".IndexOf("ae")); // prints '8' (my machine is set to en-US)

هذا التناقض موجود منذ أكثر من عقد. إنه موثق وهناك إرشادات بشأنه. هل هو تصميم خاطئ؟ ربما. نحن نناقش على https://github.com/dotnet/runtime/issues/43956 طرقًا لجعل النظام البيئي أكثر صحة للمضي قدمًا.

بالنسبة لهذه المشكلة المحددة ، ما نسأله لأنفسنا حقًا هو: "بالنظر إلى أن التناقض كان موجودًا إلى الأبد ، إلى أي مدى يُسمح لهاتين الطريقتين بالانحراف - في الممارسة - قبل أن يضر النظام البيئي الأكبر؟" أعتقد أننا ما زلنا نحاول تحديد المكان الذي يجب أن تكون فيه هذه العتبة. تعد مثل هذه التقارير مفيدة _ للغاية_ لأنها تقدم لنا نظرة ثاقبة على الأشخاص الذين يستخدمون واجهات برمجة التطبيقات هذه في الممارسة العملية وتوقعات العملاء بشأن سلوكهم. بصفتنا مشرفين على إطار العمل ، نحتاج إلى النظر ليس فقط في الوثائق الفنية ، ولكن أيضًا في الطريقة التي تستهلك بها تطبيقات العالم الحقيقي واجهات برمجة التطبيقات هذه.

لا يُقصد بهذا التعليق حقًا الدفاع عن أي وجهة نظر معينة. هدفي هو توضيح بعض المفاهيم الخاطئة التي رأيتها والمساعدة في شرح كيفية صياغة المشكلة.

حتى إذا تم تحديد InvariantCulture ، فهل من الصحيح أن \n لا يتطابق في إصدار ICU؟

image
image

ربما ، الكود التالي يعرض 5 على Linux و -1 على Windows إذا استخدمنا git وإعداداته الافتراضية (autocrlf = true)؟

using System;

var s = @"hello
world";
Console.WriteLine(s.IndexOf("\n", StringComparison.InvariantCulture));

ufcpp نعم ، لكل وحدة العناية المركزة هذا هو السلوك المتوقع ، كما تمت مناقشته سابقًا في هذا الموضوع. يعتبر الحرفان <CR><LF> عندما يكونان متجاورين مع بعضهما البعض وحدة غير قابلة للكسر للأغراض اللغوية. لن ينتج عن البحث عن <LF> باستخدام مقارنة لغوية (مثل _InvariantCulture_) أي تطابق نظرًا لأنه سيؤدي إلى تقسيم هذه الوحدة غير القابلة للكسر.

أرغب في مشاركة تحديث مع الجميع: لقد قررنا الاحتفاظ بوحدة العناية المركزة كخيار افتراضي لـ 5.0 GA. سننظر في تحسين مأزق استخدام المقارنة اللغوية عن طريق الخطأ عندما كان المقصود ترتيبيًا ، وهذا يتم تتبعه في https://github.com/dotnet/runtime/issues/43956. سنتواصل أيضًا مع بعض المكتبات التي حددناها على أنها متأثرة بهذه المشكلة. في الأيام القادمة ، سنشارك المزيد من المستندات لمرافقة الإصدار 5.0 القادم الذي سيساعد الأشخاص على تحديد الكود المشكل بشكل أفضل وإصلاحه لتجنب هذه المشكلة.

كان هذا قرارًا صعبًا للغاية وكان علينا أن نزن تأثير التوافق على النظام البيئي مقابل محرك الأقراص للتوحيد القياسي عبر الأنظمة الأساسية.

سنترك هذه المشكلة مفتوحة للنظر في المزيد من التخفيف لمشكلة \r\n في الخدمة إذا تم تحديد أن عوامل التخفيف الحالية غير كافية.

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

هناك قاعدة محلل لتحديد StringComparison دائمًا.

https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1307

أرغب في مشاركة تحديث مع الجميع: لقد قررنا الاحتفاظ بوحدة العناية المركزة كخيار افتراضي لـ 5.0 GA. سننظر في تحسين مأزق استخدام المقارنة اللغوية عن طريق الخطأ عندما كان المقصود هو الترتيب الترتيبي ، والذي تم تتبعه في # 43956. سنتواصل أيضًا مع بعض المكتبات التي حددناها على أنها متأثرة بهذه المشكلة. في الأيام القادمة ، سنشارك المزيد من المستندات لمرافقة الإصدار 5.0 القادم الذي سيساعد الأشخاص على تحديد الكود المشكل بشكل أفضل وإصلاحه لتجنب هذه المشكلة.

كان هذا قرارًا صعبًا للغاية وكان علينا أن نزن تأثير التوافق على النظام البيئي مقابل محرك الأقراص للتوحيد القياسي عبر الأنظمة الأساسية.

سنترك هذه المشكلة مفتوحة للنظر في المزيد من التخفيف لمشكلة \r\n في الخدمة إذا تم تحديد أن عوامل التخفيف الحالية غير كافية.

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

أرغب في معرفة ما إذا كان لا يزال بإمكاني استخدام تبعيات .NET Standard التي ليس لدي سيطرة عليها.

أظن أنني لن أكون قادرًا على ذلك. ماذا عن التأكد من انتقال الأشخاص ، لا أعرف ، إلى .NET Standard 2.2؟ تغيير API؟

حتى أتمكن من معرفة حقيقة أنني أحصل على السلوك المتوقع.

لست متأكدًا من كيفية تجنب كسر النظام البيئي الحالي ، الذي لديه نصيبه العادل من المشكلات بالفعل.

سأكون سعيدًا لأن أكون مخطئًا ، يرجى القيام بذلك مع التحيز - سيريح ذهني :)

تضمين التغريدة

أرغب في معرفة ما إذا كان لا يزال بإمكاني استخدام تبعيات .NET Standard التي ليس لدي سيطرة عليها.

بشكل عام ، من المفترض أن تكون مكتبات .Net القياسية عبر الأنظمة الأساسية. وإذا كانت بعض المكتبات تعمل بشكل صحيح على .Net Core 3 على Unix اليوم (والذي يستخدم ICU) ، فمن المؤكد أنه سيعمل أيضًا على NET 5 على Windows (والذي يستخدم أيضًا ICU).

NET Standard 2.2

.Net Standard vNext موجود بشكل فعال ، على الرغم من أنه يسمى ".Net 5.0" (على سبيل المثال ، إذا كنت تكتب مكتبة ولا تهتم بدعم الأطر القديمة ، فستستهدف اليوم .Net Standard 2.1. في غضون شهر ، ستستهدف .Net 5.0 بدلاً من ذلك.)

svick فهمت. أعتقد أنني فهمت بالفعل كيفية عمل .NET Standard. أتفهم أن NET 5 هو معيار .NET الجديد ، كما كان.

أعتذر ولكني ما زلت غير متأكد مما يحدث عندما أشير إلى مكتبة .NET Standard 2.1 التي اعتمدت على عدم اتساق سلوك موجود مسبقًا بين IndexOf و Contains.

ما يتغير هنا هو شيء خارج النطاق ، ICU مقابل NLS. يوسع هذا التغيير التناقض الذي كان لدينا بالفعل ، ويكسر التوقعات.
لا يوجد شيء لترميز هذه المعلومات في libs.

لا أفهم جميع الآثار المترتبة ، لكن لا يمكنني التخلص من الشعور بأننا "على صواب تقنيًا" بدون مسار داخلي سلس للوصول إلى الوضع الطبيعي الجديد. وهو ما تمس الحاجة إليه.

كما ذكر شخص آخر ، فإن معظم الناس لا يدركون حتى ميزات اللغة الجديدة ، ناهيك عن التغيرات الزلزالية مثل هذه التي اكتشفها بشكل عشوائي أفضل أعضاء مجتمعنا. ما هي الفرص التي يمكننا تحملها؟

أرغب في معرفة ما إذا كان لا يزال بإمكاني استخدام تبعيات .NET Standard التي ليس لدي سيطرة عليها.

ما يتغير هنا هو شيء خارج النطاق ، ICU مقابل NLS. يوسع هذا التغيير التناقض الذي كان لدينا بالفعل ، ويكسر التوقعات.

لا ، لا. لا يمكن التأكيد هنا بما فيه الكفاية على أن وحدة العناية المركزة ICU قد تم استخدامها دائمًا على نظام Unix. من المفترض أن تكون مكتبات .NET Standard محمولة حسب التصميم وأي شيء عمل سابقًا على Linux .NET Core 3.x سيعمل في .NET 5.

معظم العمل الذي نقوم به هو InvariantCulture ، والذي من المفترض حسب فهمي السابق أن يكون ثابتًا حسب التصميم.

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

هل نظر فريق .NET في الألم والمشكلات والتكلفة التي قد يسببها ذلك؟

مثل هذه التصريحات تزعجني بلا نهاية. أي رمز ينقطع فجأة مع هذا التغيير كان غير صحيح في البداية. كيف يفترض أن تتقدم المنصة إذا كان على فريق .NET أن يحتفظ بسلوك كود المستخدم غير الصحيح أو يعتمد على تفاصيل التنفيذ؟ ليس الأمر كما لو أنهم لم يقدموا مفتاح توافق. كان جزء كبير من سبب انفصال NET Core عن .NET Framework هو حل هذه المشكلة من خلال ميزات مثل عمليات التثبيت جنبًا إلى جنب وعمليات نشر وقت تشغيل التطبيقات المحلية. إذا لم تتمكن من الانتقال إلى .NET 5 بسبب هذا ، فلا تنتقل إلى .NET 5.

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

إذا قمت بسحق كل أخطاء اختلاف النظام الأساسي كما تدعي ، فلا داعي للقلق.

هل نظر فريق .NET في الألم والمشكلات والتكلفة التي قد يسببها ذلك؟

مثل هذه التصريحات تزعجني بلا نهاية.

يتم تشغيل الملايين من المشاريع على .NET ويتم معالجة السلسلة بشكل متكرر للغاية.
الجهد الذي يتطلبه فريق .NET لإصلاح / تغيير هذا هو جهد ضئيل مقارنة بالجهد المطلوب للتحقق من جميع التعليمات البرمجية الحالية التي سيتم ترحيلها إلى .NET 5/6.

لذا ، من العدل أن نسأل عن "الخطة" لمعالجة هذا الأمر.
هل هناك خطة؟
هل تم تقدير تأثير هذا التغيير؟
هل هو 0.001٪ من جميع المشاريع؟ هل هو 75٪؟
ما هي التغييرات الأخرى المماثلة التي لا نعرف عنها؟

ربما يؤثر هذا فقط على عدد قليل من المشاريع.
لكن هل تم تقديره؟

راجع للشغل ، أنا جميعًا لكسر التغييرات نظرًا لسبب وجيه كافٍ. لكننا نحتاج أيضًا إلى مسار هجرة غير محفوف بالمخاطر.

petarrepac لا تفهموني خطأ ، أنا أفهم ذلك. ولكن كما أشير عدة مرات في هذا الموضوع:

  1. هناك خطة ، وهي توفير مفتاح تكوين وقت التشغيل.
  2. السلوك الذي يُزعم أنه تم كسره هو السلوك الحالي لـ .NET على جميع الأنظمة الأساسية بخلاف Windows.
  3. يجب أن يؤثر هذا فقط على الكود الذي يؤدي عمليات حساسة للثقافة حيث كان المقصود الترتيبي.

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

100٪ من العدل أن نسأل عن هذا ، لكن الأشخاص الذين يكتبون تعليقات مثل تلك التي نقلتها غالبًا ما يفترضون فقط أنه لم يتم وضع أي اعتبار وكتابته قبل محاولة فهم الصورة الأكبر وراء التغيير.

اهلا جميعا. أردنا تقديم ملخص موجز للإجراءات التي اتخذناها عندما كانت هذه المشكلة مفتوحة وفي النهاية لماذا قررنا الاحتفاظ بالإعداد الافتراضي في تحديث Windows 10 May 2019 أو ما بعده ليكون ICU لـ .NET 5.0.

عندما تم فتح القضية ، بدأنا بعض المناقشات الداخلية حول التأثير المحتمل والألم الذي يمكن أن يحدث مع عملائنا نظرًا لعدم الاتساق بين Contains(string) وهو Ordinal و IndexOf(string) أن تكون مدركًا للثقافة ، بالإضافة إلى وجود واجهات برمجة تطبيقات أخرى تدرك الثقافة بشكل افتراضي عند التشغيل عبر سلسلة ، ولكن تكون Ordinal عند التشغيل على Span<char> أو ReadOnlySpan<char> . لذلك بعد المناقشات حول هذه المشكلة ، بدأنا في إجراء تحليل لحزم NuGet التي قد تتأثر وجمع البيانات للحصول على صورة واضحة. كانت هذه النتائج التي توصلنا إليها:

  • "\ n" هو رقم 30 في "السلسلة الحرفية الأكثر استخدامًا" التي تم تمريرها إلى IndexOf و LastIndexOf و EndsWith و StartsWith و Compare و CompareTo.
  • 1٪ من المكالمات إلى String.EndsWith تكون بسلسلة بحث تبدأ بـ \ n. سيتم كسر أي من هذه الاستدعاءات حيث تحتوي السلسلة التي يتم اختبارها على "نهايات سطر بنمط windows".
  • هناك 2040 معرفات حزمة مستضافة على NuGet.org حيث يحتوي الإصدار على تجميع مع موقع اتصال معرض للخطر.
  • الغالبية العظمى من هذه الاستدعاءات هي EndsWith و IndexOf ، وهو ما يتوافق مع الفرضية القائلة بأن هذا النمط يُستخدم غالبًا لخوارزميات ساذجة لكسر الأسطر.

من حزم 2040 التي تحتوي على موقع اتصال معرض للخطر ، تدعم 539 فقط بعض إصدارات .NET Standard أو .NET Core ، مما يعني أن 0.54٪ فقط من الحزم المدرجة في NuGet.org من المحتمل أن تتعرض للانقطاع.

نظرنا إلى الحزم في قائمة الـ 539 معرّفات الحزم المحتمل تأثرها للحصول على فكرة عن التأثير الفعلي عليها. نظرنا إلى أفضل 70 (من خلال عدد التنزيلات) ، 20 منها لم تكشف عن النمط في الإصدار الأخير ، من تلك التي كشفت عن النمط لم يكن بإمكاننا سوى النظر إلى 32 لديها ترخيص متساهل:

  • 14 لم تكن خاضعة للخلل
  • 13 كان يحتمل كسرها
  • 5 غير مؤكد (لم يكن هناك مؤشر واضح على الفواصل بسبب الترميز الدفاعي لأنماط كسر السطر المتنوعة أو عوامل التخفيف الأخرى).

هذا يعني أنه من بين أفضل 70 حزمة عن طريق التنزيل ، كان من المحتمل أن يتأثر 18٪ فقط.

هذه النسب المئوية مكدسة وليس مقابل العدد الإجمالي للحزم على NuGet.org وهو 229،536. لذلك إذا استخدمنا العدد الإجمالي للحزم والعدد الإجمالي للتنزيلات في NuGet.org ، فسننظر في 539 حزمة من المحتمل أن تتأثر من 229،536 والتي تمثل 0.24٪.

وعلى الرغم من أنه من الرائع بالنسبة لنا تحليل المكتبات ، فإن nuget لا يمثل سوى جزء صغير من كود C # الموجود هناك. وحتى إذا كان شخص ما يمتلك الكود ، أ) قد لا يكون من السهل تعقب الأخطاء ، و ب) ربما لم يعد لديهم المصدر بالفعل.

ومع ذلك ، كان هذا مصدرًا جيدًا للبيانات لاستنتاج أنه على الرغم من أن هذا قد يكون تغييرًا ملحوظًا في السلوك ، إلا أنه حدث فاصل بالفعل على Unix عند قراءة المدخلات التي قد تحتوي على Windows Line Endings (والتي قد لا تكون شائعة جدًا).

في .NET Core و .NET 5+ ، نسعى جاهدين لتحقيق الاتساق عبر أنظمة التشغيل ونظرًا لتأثير هذا التغيير ، فقد شعرنا بأنه الشيء الصحيح الذي يجب القيام به. نحن نهتم بالتوافق ، وبالتالي نوفر مفتاح وقت تشغيل متوافق للأشخاص حتى يتمكنوا من العودة إلى السلوك القديم.

أيضًا ، استنتاج من الحزم التي يمكننا فحصها ، نظرًا لأن السلوك مختلف في Unix بالفعل ، فقد رأينا الكثير من البرمجة الدفاعية ضد هذه المشكلة ، للتخفيف من الانقطاعات المحتملة عبر أنظمة التشغيل.

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

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

نشكرك على كل ملاحظاتك القيمة لأنها دائمًا ما تأخذنا إلى مكان أفضل وسنحاول مواصلة تحسين هذه التجربة لـ .NET 6 ، كما تمت مناقشته في: https://github.com/dotnet/runtime/issues/43956

نظرًا لأننا نتفهم الألم الذي قد يسببه هذا بسبب الاختلافات بين نهايات الأسطر عبر نظامي التشغيل Unix و Windows ، فإننا نبقي هذه المشكلة مفتوحة وسنبحث في طريقة ممكنة للتخفيف من حالة \r\n لـ .NET 5.0 .x والتي يجب أن تكون جزءًا من إصدار الخدمة.

يوجد أيضًا اختلاف مع char و string:

Console.WriteLine("com/test/test/test/a/b/ʹ$ʹ".IndexOf("$"));
Console.WriteLine("com/test/test/test/a/b/ʹ$ʹ".IndexOf('$'));
-1
24

mattleibow عند استخدام البحث عن الأحرف ، يتم إجراء بحث ترتيبي. المستند https://docs.microsoft.com/en-us/dotnet/api/system.string.indexof؟view=net-5.0#System_String_IndexOf_System_Char_ والذي ينص على This method performs an ordinal (culture-insensitive) search . إذا قمت بالبحث عن سلسلة باستخدام الخيار الترتيبي ، فستحصل على نفس نتيجة الحرف.

C# Console.WriteLine("com/test/test/test/a/b/ʹ$ʹ".IndexOf("$", StringComparison.Ordinal));

~ يبدو أن CA1307 يعمل فقط على indexof(char) لكن ليس indexof(string) . هل هناك قاعدة لإصدار string ؟ يبدو هذا أكثر أهمية لأن الإعداد الافتراضي char يستخدم تلقائيًا ترتيبيًا ولا يؤثر تغيير الكسر على ذلك حقًا ، بينما تغير سلوك string وتحتاج إلى تحديد ترتيبي لاستعادة السلوك في بعض الحالات

~ كيف تكتشف indexof(string) ؟ ~

وجدتها ، إنها القاعدة CA1310. مستنداتنا خاطئة لـ https://docs.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu#use -nls-بدلاً من-icu ولا تذكر هذا الاختلاف المحدد. سوف أقوم بتحديث تلك المستندات.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات