لماذا لا أستطيع أن أكون مضغوطًا مع تعدد أشكال C# المرغوب فيه؟

StackOverflow https://stackoverflow.com/questions/1615351

  •  06-07-2019
  •  | 
  •  

سؤال

إليك ما أريد أن أفعله:

XmlWriter writer = XmlWriter.Create(
    (string.IsNullOrEmpty(outfile) ? Console.Out : outfile)
);

ومع ذلك، لا يتم تجميع هذا، مما يؤدي إلى ظهور الخطأ "لا يمكن تحديد نوع التعبير الشرطي لأنه لا يوجد تحويل ضمني بين 'System.IO.TextWriter' و'string'".الكود أعلاه هو تبسيط لما يلي:

XmlWriter writer;

if (string.IsNullOrEmpty(outfile))
{
    writer = XmlWriter.Create(Console.Out); // Constructor takes TextWriter
}
else
{
    writer = XmlWriter.Create(outfile); // Constructor takes string
}

هذين يدعوان إلى Create صالحة تماما، وهذا يجمع.هل هناك طريقة لجعل هذا أكثر إحكاما، كما كنت أحاول أن أفعل مع الاختبار المضمن الخاص بي؟

ليس من المنطقي بالنسبة لي أن ما أريده لا ينجح.بالتفكير عقليًا في هذا، يبدو أن المترجم سيقيمه string.IsNullOrEmpty(outfile) لتحديد الحالة التي يجب اتخاذها:

  • ولو كان الشرط صحيحا لذهب معه Console.Out, ، ثم تأكد من أنه يحتاج إلى اختيار إصدار متعدد الأشكال XmlWriter.Create الذي يأخذ TextWriter.
  • ولو كان الشرط كاذبا لذهب معه outfile, ، ثم تأكد من أنه يحتاج إلى اختيار إصدار متعدد الأشكال XmlWriter.Create الذي يأخذ سلسلة.

هل شوهت البرمجة في ML ذهني؟

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

المحلول

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

XmlWriter writer = String.IsNullOrEmpty(outfile)
    ? XmlWriter.Create(Console.Out)
    : XmlWriter.Create(outfile);

نصائح أخرى

يبدو أن الجميع يقترح ما يلي:

XmlWriter writer = String.IsNullOrEmpty(outfile)
    ? XmlWriter.Create(Console.Out)
    : XmlWriter.Create(outfile);

ومع ذلك، هذا ممكن أيضًا:

XmlWriter writer = XmlWriter.Create(string.IsNullOrEmpty(outfile)
    ? Console.Out : new StreamWriter(outfile));

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

يختار مترجم C# طريقة للتنفيذ بشكل ثابت أثناء الترجمة.يعد IL الذي يتم إنشاؤه عند التجميع مرجعًا لطريقة معينة.يأتي جزء تعدد الأشكال في وقت التشغيل عندما يختار تنفيذ تلك الوظيفة المحددة المراد تنفيذها.

لك ؟:يتم تقييم العبارة في وقت التشغيل، وبالتالي لا يستطيع المترجم معرفة الطريقة التي سيتم تنفيذها.

قم بالتغيير إلى هذا وسيعمل.

XmlWriter writer = string.IsNullOrEmpty(outfile) ? 
    XmlWriter.Create(Console.Out) :
    XmlWriter.Create(outfile);

المشكلة هي أنه لا يمكنك تحديد ما هو وقت الترجمة

(string.IsNullOrEmpty(outfile) ? Console.Out : outfile)

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

ربما يكون أفضل ما يمكنك الخروج منه هو:

XmlWriter writer = string.IsNullOrEmpty(outfile)
    ? XmlWriter.Create(Console.Out)
    : XmlWriter.Create(outfile);

هناك شيئان يحدثان هنا.

أولاً، يحدث "الاستثناء" بسبب The Ternary Operator (tm)، وليس بسبب المكان الذي تستخدمه فيه.تكمن المشكلة في أن لديك تعبيرًا واحدًا يحاول إرجاع نوعين مختلفين لا يمكن حلهما لنوع أساسي واحد مشترك (بخلاف الكائن).

علاوة على ذلك، من المحتمل أن تأخذ الأحمال الزائدة للمنشئ نوعين مختلفين تمامًا وغير مرتبطين بأي شكل من الأشكال.المترجم C # للغاية، جداً ذكية، ولكنها ليست تماما الذي - التي ذكي.

لا، يجب عليك إجراء مكالمتين منفصلتين، حيث أنهما منشئان منفصلان.

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

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

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

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