هل من الممكن لخلق المختصة بالبت تعداد عام "IsOptionSet () 'طريقة؟

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

سؤال

ورمز أدناه يجعل من السهل أن يمر في مجموعة HtmlParserOptions ومن ثم تحقق ضد خيار واحد لمعرفة ما إذا تم تحديده.

[Flags]
public enum HtmlParserOptions
{
    NotifyOpeningTags = 1,
    NotifyClosingTags = 2,
    NotifyText = 4,
    NotifyEmptyText = 8
}

private bool IsOptionSet(HtmlParserOptions options, HtmlParserOptions singleOption)
{
    return (options & singleOption) == singleOption;
}

وسؤالي هو، هل من الممكن لإنشاء نسخة عام من هذا (انا التخمين من خلال تنفيذ واجهة على خصائص الأسلوب) التي ستعمل مع أي تعداد مع أعلام يعزو <؟ / P>

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

المحلول

وتحرير:

وأسهل، اجمل الخيار للترقية إلى VS2010 Beta2 واستخدام .NET Framework 4 في <لأ href = "http://msdn.microsoft.com/en-us/library/system.enum.hasflag(VS.100) .aspx اتصال "يختلط =" noreferrer "> Enum.HasFlag الأسلوب. وأضاف الفريق إطار الكثير من الإضافات لطيفة لالتعداد لجعلها أجمل للاستخدام.


والأصل (ل. NET الحالي):

ويمكنك القيام بذلك عن طريق تمرير التعداد، بدلا من الأدوية:

static class EnumExtensions
{
    private static bool IsSignedTypeCode(TypeCode code)
    {
        switch (code)
        {
            case TypeCode.Byte:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
                return false;
            default:
                return true;
        }
    }

    public static bool IsOptionSet(this Enum value, Enum option)
    {
        if (IsSignedTypeCode(value.GetTypeCode()))
        {
            long longVal = Convert.ToInt64(value);
            long longOpt = Convert.ToInt64(option);
            return (longVal & longOpt) == longOpt;
        }
        else
        {
            ulong longVal = Convert.ToUInt64(value);
            ulong longOpt = Convert.ToUInt64(option);
            return (longVal & longOpt) == longOpt;
        }
    }
}

وهذا يعمل تماما، كما يلي:

class Program
{
    static void Main(string[] args)
    {
        HtmlParserOptions opt1 = HtmlParserOptions.NotifyText | HtmlParserOptions.NotifyEmptyText;
        Console.WriteLine("Text: {0}", opt1.IsOptionSet(HtmlParserOptions.NotifyText));
        Console.WriteLine("OpeningTags: {0}", opt1.IsOptionSet(HtmlParserOptions.NotifyOpeningTags));

        Console.ReadKey();
    } 
}

وطباعة أعلاه:

Text: True
OpeningTags: False

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

نصائح أخرى

حسنا، من النوع.

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

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

if (options.HasAny(optionToTest))

أو

if (options.HasAll(optionToTest))

واعتمادا على الطريقة التي يريد معالجة الحالة حيث optionToTest هو في الواقع عدة أعلام مجتمعة.

وبدلا من ذلك، انتظر NET 4.0 - في تغييرات في BCL تشمل <لأ href =" http://msdn.microsoft.com/en- لنا / مكتبة / system.enum.hasflag (VS.100) .ASPX "يختلط =" نوفولو noreferrer "> Enum.HasFlag ، التي أعتقد أن تفعل ما تريد.

public static bool IsOptionSet<T>(this T flags, T option) where T : struct
{
    if(! flags is int) throw new ArgumentException("Flags must be int");

    int opt = (int)(object)option;
    int fl = (int)(object)flags;
    return (fl & opt) == opt;
}

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

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