সি # তে জেনেরিক ব্যতিক্রমের সমস্ত রূপগুলি কীভাবে ধরবেন


22

আমি জেনেরিক ব্যতিক্রম শ্রেণীর সমস্ত রূপগুলি ধরতে চাই এবং আমি ভাবছিলাম যে একাধিক ক্যাচ ব্লক ছাড়াই এটি করার কোনও উপায় আছে কিনা। উদাহরণস্বরূপ বলুন আমার একটি ব্যতিক্রম শ্রেণী রয়েছে:

public class MyException<T> : Exception
{
    public string MyProperty { get; }

    public MyException(T prop) : base(prop.ToString())
    {
        MyProperty = prop?.ToString();
    }
}

এবং দুটি উত্পন্ন ক্লাস:

public class MyDerivedStringException : MyException<string>
{
    public MyDerivedStringException(string prop) : base(prop)
    {

    }
}

public class MyDerivedIntException : MyException<int>
{
    public MyDerivedIntException(int prop) : base(prop)
    {

    }
}

উভয় MyDerivedStringExceptionএবং MyDerivedIntExceptionএকটি ক্যাচ ব্লকে ধরার উপায় আছে ?

আমি এটি চেষ্টা করেছি:

try
{
   ...
}

catch(Exception e) when (e is MyDerivedStringException || e is MyDerivedIntException)
{
}

তবে এটি খুব পরিষ্কার নয় এবং এর অর্থ হল আমার অ্যাক্সেস নেই MyProperty

আমি সমস্যার সাধারণ সমাধানে আগ্রহী কিন্তু আমার ক্ষেত্রে জেনেরিক ব্যতিক্রম একটি তৃতীয় পক্ষের লাইব্রেরিতে সংজ্ঞায়িত করা হয়েছে যা নীচে বর্ণিত হিসাবে সমস্যাটিতে কিছু অতিরিক্ত বাধা যুক্ত করে।

উত্তর:


15

MyException<T>একটি ইন্টারফেস বাস্তবায়ন করুন এবং ইন্টারফেস ধরণের দ্বারা একটি ব্যতিক্রম পরীক্ষা করুন ।

ইন্টারফেস:

public interface IMyException
{
    string MyProperty { get; }
}

ইন্টারফেস প্রয়োগকারী জেনেরিক ক্লাস:

public class MyException<T> : Exception, IMyException
{
    public string MyProperty { get; }

    public MyException(T prop)
    {
        MyProperty = prop?.ToString();
    }
}

উত্পন্ন ক্লাস:

public class MyDerivedStringException : MyException<string>
{
    public MyDerivedStringException(string prop) : base(prop)
    {

    }
}

public class MyDerivedIntException : MyException<int>
{
    public MyDerivedIntException(int prop) : base(prop)
    {

    }
}

ব্যবহার:

try
{
    // ...
}
catch (Exception e) when (e is IMyException)
{
    // ...
}

বেস ক্লাস থেকে প্রাপ্ত Exceptionএবং তার চেয়ে উত্তরাধিকার সূত্রে একটি বেস ক্লাস তৈরি করেও এটি করা যেতে পারে MyException<T>


3
আমি নিশ্চিত নই যে এটি এখানে একটি ইন্টারফেসের জন্য মূল্যবান - কেবল একটি জেনেরিক বেস শ্রেণীর মধ্যে Exceptionএবং MyException<T>এটি ভাল হবে।
জন স্কিটি

এছাড়াও, ওপির এখনও জেনেরিক সম্পত্তি (প্রতিবিম্ব ব্যবহার না করে) অ্যাক্সেস নেই যা আমার ধারণা যে আসল সমস্যা।
ডেভিডজি

10

যদি আপনার Typeজেনেরিক থেকে উত্পন্ন হয় তবে পরীক্ষাটি হ'ল:

Type = typeof(something);
t.GetGenericTypeDefinition()==typeof(MyException<>);

তবে এটি কেবল ডাইরেক্টেড প্রকারের জন্যই পছন্দ, যেমন MyException<int>বা MyException<string>

আপনার যদি আরও ডেরাইভেটিভ থাকে তবে MyDerivedStringExceptionআপনাকে পরীক্ষা করতে হয়েছিল:

ex.GetType.BaseType.GetGenericTypeDefinition()==typeof(MyException<>);

সুতরাং এটি যে কোনও বিদ্যমান জেনেরিকের জন্য কাজ করে তবে আপনার এই পরীক্ষার উত্তরাধিকারের স্তরটি বা সমস্ত বেস ধরণের লুপটি জানতে হবে।

সুতরাং আপনি এটি করতে পারে:

catch(Exception ex) when (ex.GetType.BaseType.GetGenericTypeDefinition()==typeof(MyException<>))

3

এই প্রয়োগকারী বাক্সগুলি এবং আনবক্সগুলি যদি টি: মানটি হল ভেলুয়টাইপ ... তবে ব্যবহারের ক্ষেত্রে আপনি বক্স / আনবক্সে বার বার চেষ্টা করার সাথে পারফরম্যান্সের প্রভাবগুলি নিয়ন্ত্রণ করতে পারেন।

public class MyException<T> : MyException
{
    public T Prop => (T)base.Prop;

    public MyException(T prop) : base(prop)
    {

    }
}

public class MyException : Exception
{
    protected object Prop { get; }

    public MyException(object prop)
    {
         Prop = prop;
    }
}

যুক্তিবিদ্যা

try {
     ...
} catch(MyException e) {
    ...
}

এটি একটি উত্তরের উত্তর এবং আমি উজ্জীবিত হয়েছি - দুর্ভাগ্যক্রমে এটি আমার নির্দিষ্ট সমস্যাটি সমাধান করে না কারণ জেনেরিক ব্যতিক্রম তৃতীয় পক্ষের লাইব্রেরিতে রয়েছে তাই আমি এটি সম্পাদনা করতে পারি না।
এসবিফ্রেন্সি

2

দুর্ভাগ্যক্রমে, আপনি এর সাথে ধরতে পারবেন না

catch(MyException ex) বর্গ, যেমন এটি একটি ধরণের প্রত্যাশা করে।

আপনার সেরা বেটটি হবে বেস ক্লাস বা ইন্টারফেস তৈরি করা, এটি ধরা এবং সেখান থেকে টাইপটি পাওয়া।

কীভাবে টাইপ পাবেন এবং এটি কীভাবে করা যায় সে সম্পর্কে এখানে ইতিমধ্যে একটি উত্তর রয়েছে ।


1

এই বাস্তবায়ন টি / সি এর প্রসঙ্গ থেকে দূরে ব্যতিক্রমের জন্য হ্যান্ডলিং প্রতিনিধিটিকে বিমূর্ত করে তোলে ... এটি কিছুটা সাহসী হতে পারে তবে এটি সম্পর্কে দুর্দান্ত অংশটি হ'ল আপনি পুনরায় ব্যবহারের সুযোগ এবং প্রসঙ্গে নির্ভর করে বিভিন্ন হ্যান্ডলারকে ইনজেক্ট করতে পারেন is ব্যবহারের।

public interface IExceptionHandler
{
    object Handle(Exception ex);

    void RegisterExceptionTypeHandler<T>(Func<T,object> handlerDelegate) where T : Exception;
}

নিবন্ধের যুক্তি

handler.RegisterExceptionTypeHandler<MyException<int>>(ex => ...);
handler.RegisterExceptionTypeHandler<MyException<string>>(ex => ...);

try {
    ...
}catch(Exception ex)
{
    ...any validation
    return exceptionHandler.Handle(ex)
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.