سؤال

يقارن

String.Format("Hello {0}", "World");

مع

"Hello {0}".Format("World");

لماذا اختار مصممو .Net طريقة ثابتة بدلاً من طريقة المثيل؟ماذا تعتقد؟

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

المحلول

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

إذا كنت أتذكر بشكل صحيح (لم أتحقق من ذلك فعليًا لأنه ليس لدي IDE قديم في متناول يدي)، واجهت الإصدارات المبكرة من C# IDE مشكلة في اكتشاف استدعاءات الطريقة مقابل القيم الحرفية للسلسلة في IntelliSense، وهذا له تأثير كبير على قابلية الاكتشاف من واجهة برمجة التطبيقات.إذا كان الأمر كذلك، فإن كتابة ما يلي لن يقدم لك أي مساعدة:

"{0}".Format(12);

لو اضطررت للكتابة

new String("{0}").Format(12);

سيكون من الواضح أنه لا توجد ميزة في جعل أسلوب التنسيق أسلوبًا مثيلًا وليس أسلوبًا ثابتًا.

لقد تم تصميم مكتبات .NET بواسطة العديد من نفس الأشخاص الذين قدموا لنا MFC، وتحمل فئة String على وجه الخصوص تشابهًا قويًا مع فئة CString في MFC.يحتوي MFC على أسلوب تنسيق المثيل (الذي يستخدم رموز تنسيق نمط printf بدلاً من نمط القوس المتعرج لـ .NET) وهو أمر مؤلم لأنه لا يوجد شيء مثل CString الحرفي.لذلك في قاعدة بيانات MFC التي عملت عليها أرى الكثير من هذا:

CString csTemp = "";
csTemp.Format("Some string: %s", szFoo);

وهو أمر مؤلم.(أنا لا أقول أن التعليمات البرمجية أعلاه هي طريقة رائعة للقيام بالأشياء حتى في MFC، ولكن يبدو أن هذه هي الطريقة التي تعلم بها معظم المطورين في المشروع كيفية استخدام CString::Format).وانطلاقًا من هذا التراث، أستطيع أن أتخيل أن مصممي واجهة برمجة التطبيقات (API) كانوا يحاولون تجنب هذا النوع من المواقف مرة أخرى.

نصائح أخرى

لأن أسلوب التنسيق لا علاقة له بالقيمة الحالية للسلسلة.

هذا صحيح ل الجميع طرق السلسلة لأن سلاسل .NET غير قابلة للتغيير.

إذا كانت غير ثابتة، فستحتاج إلى سلسلة لتبدأ بها.

نعم هو كذلك:سلسلة التنسيق.

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

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

"Hello {0}".Format("World"); // this makes it sound like Format *modifies* 
                             // the string, which is not possible as 
                             // strings are immutable.

string[] parts = "Hello World".Split(' ');    // this however sounds right, 
                                             // because it implies that you 
                                             // split an existing string into 
                                             // two *new* strings.

أول شيء قمت به عندما قمت بالترقية إلى VS2008 وC#3، هو القيام بذلك

public static string F( this string format, params object[] args )
{
    return String.Format(format, args);
}

لذا يمكنني الآن تغيير الكود الخاص بي من

String.Format("Hello {0}", Name);

ل

"Hello {0}".F(Name);

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

أما لماذا اختاره مصممو .NET؟من تعرف.يبدو ذاتيًا تمامًا.أموالي على سواء

  • نسخ جافا
  • الرجل الذي كتبه في ذلك الوقت أحبه بشكل شخصي أكثر.

لا توجد حقًا أي أسباب صحيحة أخرى يمكنني العثور عليها

أعتقد أن السبب هو أن التنسيق لا يأخذ سلسلة في حد ذاته، بل "سلسلة تنسيق".معظم السلاسل تساوي أشياء مثل "Bob Smith" أو "1010 Main St" أو ما لديك وليس "Hello {0}"، بشكل عام، فإنك لا تضع سلاسل التنسيق هذه إلا عندما تحاول استخدام قالب لإنشاء قالب آخر سلسلة، مثل طريقة المصنع، وبالتالي فهي تضفي نفسها على الطريقة الثابتة.

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

لأن أسلوب التنسيق لا علاقة له بالقيمة الحالية للسلسلة.لم يتم استخدام قيمة السلسلة.يستغرق سلسلة ويعيد واحدة.

ربما قام مصممو .NET بذلك بهذه الطريقة لأن JAVA فعلت ذلك بهذه الطريقة...

احتضان وتوسيع.:)

يرى: http://discuss.techinterview.org/default.asp?joel.3.349728.40

سلاسل .NET غير قابلة للتغيير
لذلك فإن وجود طريقة مثيل ليس له أي معنى على الإطلاق.

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

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

لماذا لا هذا؟انها تتفق مع بقية إطار عمل .NET

"Hello {0}".ToString("Orion");

تعد أساليب المثيل جيدة عندما يكون لديك كائن يحتفظ بحالة معينة؛لا تؤثر عملية تنسيق السلسلة على السلسلة التي تعمل عليها (اقرأ:لا يعدل حالته)، فإنه ينشئ سلسلة جديدة.

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

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

جانبًا، جميع وظائف فئة السلسلة لا تعمل على السلسلة، ولكنها تُرجع كائن سلسلة جديدًا، لأن السلاسل غير قابلة للتغيير.

@ جاريد:

الأساليب الثابتة غير المحملة وغير الموروثة (مثل Class.b(a,c)) التي تأخذ مثيلًا كمتغير أول تكون مكافئة لغويًا لاستدعاء الأسلوب (مثل a.b(c))

لا، ليسوا كذلك.

(بافتراض أنه يتم التحويل البرمجي إلى نفس CIL، وهو ما ينبغي.)

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

لكن، String.Format يفعل لا يسمح null القيم لذا كان على المطورين إدخال شيك يدويًا.من وجهة النظر هذه، سيكون متغير طريقة العضو متفوقًا من الناحية الفنية.

وهذا لتجنب الخلط مع .ToString() طُرق.

على سبيل المثال:

double test = 1.54d;

//string.Format pattern
string.Format("This is a test: {0:F1}", test );

//ToString pattern
"This is a test: " + test.ToString("F1");

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

String.Format() هي طريقة مساعدة لتحويل كائنات متعددة إلى سلسلة منسقة.

طريقة المثيل على سلسلة تفعل شيئًا ما لتلك السلسلة.

بالطبع، يمكنك القيام بما يلي:

public static string FormatInsert( this string input, params object[] args) {
    return string.Format( input, args );
}

"Hello {0}, I have {1} things.".FormatInsert( "world", 3);

لا أعرف لماذا فعلوا ذلك، لكن الأمر لم يعد مهمًا بعد الآن:

public static class StringExtension
{
    public static string FormatWith(this string format, params object[] args)
    {
        return String.Format(format, args);
    }
}

public class SomeClass
{
    public string SomeMethod(string name)
    {
        return "Hello, {0}".FormatWith(name);
    }
}

أن يتدفق أسهل كثيرا، IMHO.

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

سبب آخر ل String.Format هو التشابه في الوظيفة printf من C.كان من المفترض أن يتيح لمطوري لغة C وقتًا أسهل في تبديل اللغات.

لا أرى أي عيب في كونها ثابتة..

يبدو أن دلالات الطريقة الثابتة أكثر منطقية بالنسبة لي.ربما لأنه بدائي.عندما يتم استخدام البدائيات في كثير من الأحيان، فأنت تريد أن تجعل التعليمات البرمجية المساعدة للعمل معها خفيفة قدر الإمكان.أيضًا، أعتقد أن الدلالات أفضل كثيرًا String.Format زيادة "MyString بلاه بلاه {0}".التنسيق ...

الأساليب الثابتة غير المحملة وغير الموروثة (مثل Class.b(a,c)) التي تأخذ مثيلًا كمتغير أول تكون مكافئة لغويًا لاستدعاء الطريقة (مثل a.b(c)) لذا قام فريق النظام الأساسي بإجراء تعسفي، الاختيار الجمالي.(بافتراض أنه يتم التحويل البرمجي إلى نفس CIL، وهو ما ينبغي أن يحدث.) والطريقة الوحيدة لمعرفة ذلك هي أن تسألهم عن السبب.

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

String.Format("Foo {0}", "Bar");

بدلاً من

"Foo {0}".Format("bar");

تريد أن تعرف ما تم تعيين الفهارس إليه؛ربما ظنوا أن الجزء ".Format" يضيف ضوضاء في المنتصف.

ومن المثير للاهتمام أن طريقة ToString (على الأقل بالنسبة للأرقام) هي عكس ذلك:number.ToString("000") مع سلسلة التنسيق الموجودة على الجانب الأيمن.

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

كما أجد String.Format() أكثر انسجاما مع الأساليب الثابتة المنقوشة الأخرى مثل Int32.Parse(), long.TryParse(), ، إلخ.

أنت أيضًا تستخدم السحابة فقط StringBuilder إذا كنت تريد تنسيقًا غير ثابت.StringBuilder.AppendFormat()

يجب أن تكون String.Format طريقة ثابتة لأن السلاسل غير قابلة للتغيير. إن جعلها طريقة مثيل يعني أنه يمكنك استخدامها "لتنسيق" أو تعديل قيمة سلسلة موجودة.هذا لا يمكنك القيام به، وجعله أسلوب مثيل يُرجع سلسلة جديدة لن يكون له أي معنى.وبالتالي، فهي طريقة ثابتة.

String.Format يأخذ سلسلة واحدة على الأقل ويعيد سلسلة مختلفة.لا يحتاج إلى تعديل سلسلة التنسيق من أجل إرجاع سلسلة أخرى، لذلك ليس من المنطقي القيام بذلك (تجاهل تنسيقك لها).من ناحية أخرى، لن يكون الأمر ممتدًا إلى هذا الحد String.Format تكون وظيفة عضو، إلا أنني لا أعتقد أن C# يسمح بوظائف الأعضاء الثابتة مثل C++.[الرجاء تصحيح لي وهذا المنشور إذا كان الأمر كذلك.]

سلاسل .NET غير قابلة للتغيير

لذلك فإن وجود طريقة مثيل ليس له أي معنى على الإطلاق.

String foo = new String();

foo.Format("test {0}",1); // Makes it look like foo should be modified by the Format method. 

string newFoo = String.Format(foo, 1); // Indicates that a new string will be returned, and foo will be unaltered.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top