طرح طريقة عامة لرمي نوع استثناء محدد على الفشل

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

  •  09-06-2019
  •  | 
  •  

سؤال

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

أريد أن يكون لدي طريقة يمكنني من خلالها أن أقول "إذا ساءت الأمور، عد بهذا النوع من الاستثناءات"، أليس كذلك؟

على سبيل المثال، شيء مثل (وهذا لا يعمل):

    static ExType TestException<ExType>(string message) where ExType:Exception
    {
        Exception ex1 = new Exception();
        ExType ex = new Exception(message);
        return ex;
    }

الآن ما يحيرني هو أننا يعرف أن النوع العام سيكون من نوع الاستثناء بسبب أين بند.ومع ذلك، يفشل الكود لأنه لا يمكننا الإرسال ضمنيًا استثناء ل نوع ExType.ولا يمكننا تحويلها بشكل صريح أيضًا، مثل:

    static ExType TestException<ExType>(string message) where ExType:Exception
    {
        Exception ex1 = new Exception();
        ExType ex = (ExType)(new Exception(message));
        return ex;
    }

كما فشل ذلك أيضاً..لذا هل هذا النوع من الأشياء ممكن؟ لدي شعور قوي بأن الأمر سيكون بسيطًا جدًا، لكني أواجه يومًا صعبًا مع الرأس القديم، لذا خذ مني بعض الركود:P


تحديث

شكرًا على الردود يا شباب، يبدو أنني لم أكن أنا مكتمل غبي!;)

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

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

    static ExType TestException<ExType>(string message) where ExType:Exception, new ()
    {
        ExType ex = (ExType)Activator.CreateInstance(typeof(ExType), message);
        return ex;
    }

حلو!:)

شكرا يا شباب!

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

المحلول

يمكنك فعل ذلك تقريبًا على النحو التالي:

static void TestException<E>(string message) where E : Exception, new()
{
    var e = new E();
    e.Message = message;
    throw e;
}

ومع ذلك، لا يتم تجميع ذلك لأن Exception.Message للقراءة فقط.لا يمكن تعيينه إلا عن طريق تمريره إلى المنشئ، ولا توجد طريقة لتقييد نوع عام بشيء آخر غير المنشئ الافتراضي.

أعتقد أنه سيتعين عليك استخدام الانعكاس (Activator.CreateInstance) "لتحديث" نوع الاستثناء المخصص باستخدام معلمة الرسالة، مثل هذا:

static void TestException<E>(string message) where E : Exception
{
    throw Activator.CreateInstance(typeof(E), message) as E;
}

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

نصائح أخرى

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

static void TestException<E>(string message) where E : Exception, new()
{
    try 
    {
      return Activator.CreateInstance(typeof(E), message) as E;
    } 
    catch(MissingMethodException ex) 
    {
      return new E();
    }
}

لقد قمت بإنشاء مثيل لنوع الاستثناء الذي أريد طرحه، مثل هذا:

if (ItemNameIsValid(ItemName, out errorMessage))
    throw new KeyNotFoundException("Invalid name '" + ItemName + "': " + errorMessage);
if (null == MyArgument)
    throw new ArgumentNullException("MyArgument is null");

هل حاولت بدلاً من ذلك:

static T TestException<Exception>(string message)
{}

لأنني أشعر أن وضع القيد العام ليس ضروريًا مثل جميع الاستثناءات القابلة للرمي يجب ترث من System.Exception على أي حال.

تذكر أن الأدوية الجنيسة تقبل الأنواع الموروثة.

أعتقد أن رؤية جميع الاستثناءات يجب أن تحتوي على مُنشئ بدون معلمات، وأن يكون لها Message الملكية، لذلك يجب أن يعمل ما يلي:

static ExType TestException<ExType>(string message) where ExType:Exception
{
    ExType ex = new ExType();
    ex.Message = message;
    return ex;
}

يحرر:حسنًا، الرسالة للقراءة فقط، لذا عليك أن تأمل أن ينفذ الفصل مُنشئ الاستثناء (السلسلة) بدلاً من ذلك.

static ExType TestException<ExType>(string message) where ExType:Exception
{
    return new ExType(message);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top