玩转C科技.NET

从学会做人开始认识这个世界!http://volnet.github.io

导航

The Attribute basic

本文仅仅写了一个最简单的Attribute示例,不作过多阐释,代码如下:

值得注意的是,由于Attribute是在编译时确定的,因此/*Blog = new Blog(10,"title","content"),*/ 由于Blog的确定是在运行时确定的,这样的方式将无法编译通过。

using System;
using System.Reflection;

namespace CA_Attribute
{
    /// <summary>
    /// It is only a test class
    /// </summary>
    class Blog
    {
        public Blog()
        { }
        public Blog(int id, string title, string content)
        {
            this.id = id;
            this.title = title;
            this.content = content;
        }
        private int id;
        public int ID
        { get { return id; } set { id = value; } }
        string title = string.Empty;
        public string Title
        { get { return title; } set { title = value; } }
        private string content;
        public string Content
        { get { return content; } set { content = value; } }
        public void Publish()
        {
            if (Title == string.Empty)
                Console.WriteLine("The blog is not exists!");
            else
                Console.WriteLine("The blog (id={0},title={1}) has been published at {2}!", this.ID, this.Title, DateTime.Now);
        }
    }

    public enum EnumTest
    {
        value0 = 0,
        value1 = 1,
        value2 = 2,
        value3 = 3,
        value4 = 4,
        value5 = 5,
        value6 = 6
    }

    class TestAttribute : Attribute
    {
        private int count = 50;
        public int Count
        {
            get
            { return count; }
            set
            { count = value; }
        }
        private string message = "none";
        public string Message
        {
            get
            {
                return message;
            }
            set
            {
                message = value;
            }
        }
        private Blog blog = new Blog();
        public Blog Blog
        {
            get { return blog; }
            set { blog = value; }
        }

        public EnumTest EnumValue
        {
            get;
            set;
        }
    }

    [Test(Count = 29, Message = "Good luck!", /*Blog = new Blog(10,"title","content"),*/ EnumValue = EnumTest.value6)]
    class TestClass
    {
        public int TestCount
        {
            get
            {
                TestAttribute ta = AttributeHelper.GetCustomAttribute<TestAttribute>(typeof(TestClass));
                if (ta != null)
                {
                    return ta.Count;
                }
                return int.MinValue;
            }
        }
        public string TestMessage
        {
            get
            {
                TestAttribute ta = AttributeHelper.GetCustomAttribute<TestAttribute>(typeof(TestClass));
                if (ta != null)
                {
                    return ta.Message;
                }
                return "testMessage default;";
            }
        }
        public Blog TestBlog
        {
            get
            {
                TestAttribute ta = AttributeHelper.GetCustomAttribute<TestAttribute>(typeof(TestClass));
                if (ta != null)
                {
                    return ta.Blog;
                }
                return new Blog();
            }
        }

        public EnumTest TestEnum
        {
            get
            {
                TestAttribute ta = AttributeHelper.GetCustomAttribute<TestAttribute>(typeof(TestClass));
                if (ta != null)
                {
                    return ta.EnumValue;
                }
                return EnumTest.value0;
            }
        }
    }

    internal class AttributeHelper
    {
        public static T GetCustomAttribute<T>(Type type) where T : Attribute
        {
            object[] attributes = type.GetCustomAttributes(false);
            foreach (object attribute in attributes)
            {
                if (attribute is T)
                {
                    return attribute as T;
                }
            }
            return null;
        }
        //Other Members
    }

    class Program
    {
        static void Main(string[] args)
        {
            TestClass tc = new TestClass();
            Console.WriteLine("The TestAttribute set the property of TestClass with :\n\t\t TestCount={0};TestMessage={1};TestEnum={2}", tc.TestCount, tc.TestMessage, tc.TestEnum);
            tc.TestBlog.Publish();
        }
    }
}
另外,有个用于枚举的属性相当有意思。
简而言之就是按位取。注意到以下示例中的0 1 2 4,转换为相应的16进制为0000 0001 0010 0100,恰好对应(Black,Red,Green,Blue),而假设转换数字为7,对应的十六进制为0111,因此,等价于0001|0010|0100,而使用了FlagsAttribute的项将会有Red|Green|Blue,这点与C++中的一些用法非常相似。
(以下内容来自MSDN)
FlagsAttribute Class

Bit fields are generally used for lists of elements that might occur in combination, whereas enumeration constants are generally used for lists of mutually exclusive elements. Therefore, bit fields are designed to be combined with a bitwise OR operation to generate unnamed values, whereas enumerated constants are not. Languages vary in their use of bit fields compared to enumeration constants.

Attributes of the FlagsAttribute

AttributeUsageAttribute is applied to this class, and its Inherited property specifies false. This attribute can only be applied to enumerations.

Guidelines for FlagsAttribute and Enum
  • Use the FlagsAttribute custom attribute for an enumeration only if a bitwise operation (AND, OR, EXCLUSIVE OR) is to be performed on a numeric value.

  • Define enumeration constants in powers of two, that is, 1, 2, 4, 8, and so on. This means the individual flags in combined enumeration constants do not overlap.

  • Consider creating an enumerated constant for commonly used flag combinations. For example, if you have an enumeration used for file I/O operations that contains the enumerated constants Read = 1 and Write = 2, consider creating the enumerated constant ReadWrite = Read OR Write, which combines the Read and Write flags. In addition, the bitwise OR operation used to combine the flags might be considered an advanced concept in some circumstances that should not be required for simple tasks.

  • Use caution if you define a negative number as a flag enumerated constant because many flag positions might be set to 1, which might make your code confusing and encourage coding errors.

  • A convenient way to test whether a flag is set in a numeric value is to perform a bitwise AND operation between the numeric value and the flag enumerated constant, which sets all bits in the numeric value to zero that do not correspond to the flag, then test whether the result of that operation is equal to the flag enumerated constant.

  • Use None as the name of the flag enumerated constant whose value is zero. You cannot use the None enumerated constant in a bitwise AND operation to test for a flag because the result is always zero. However, you can perform a logical, not a bitwise, comparison between the numeric value and the None enumerated constant to determine whether any bits in the numeric value are set.

    If you create a value enumeration instead of a flags enumeration, it is still worthwhile to create a None enumerated constant. The reason is that by default the memory used for the enumeration is initialized to zero by the common language runtime. Consequently, if you do not define a constant whose value is zero, the enumeration will contain an illegal value when it is created.

    If there is an obvious default case your application needs to represent, consider using an enumerated constant whose value is zero to represent the default. If there is no default case, consider using an enumerated constant whose value is zero that means the case that is not represented by any of the other enumerated constants.

  • Do not define an enumeration value solely to mirror the state of the enumeration itself. For example, do not define an enumerated constant that merely marks the end of the enumeration. If you need to determine the last value of the enumeration, check for that value explicitly. In addition, you can perform a range check for the first and last enumerated constant if all values within the range are valid.

  • Do not specify enumerated constants that are reserved for future use.

  • When you define a method or property that takes an enumerated constant as a value, consider validating the value. The reason is that you can cast a numeric value to the enumeration type even if that numeric value is not defined in the enumeration.

// Example of the FlagsAttribute attribute.
using System;

class FlagsAttributeDemo
{
    // Define an Enum without FlagsAttribute.
    enum SingleHue : short
    {
        Black = 0,
        Red = 1,
        Green = 2,
        Blue = 4
    };

    // Define an Enum with FlagsAttribute.
    [FlagsAttribute] 
    enum MultiHue : short
    {
        Black = 0,
        Red = 1,
        Green = 2,
        Blue = 4
    };

    static void Main( )
    {
        Console.WriteLine( 
            "This example of the FlagsAttribute attribute \n" +
            "generates the following output." );
        Console.WriteLine( 
            "\nAll possible combinations of values of an \n" +
            "Enum without FlagsAttribute:\n" );

        // Display all possible combinations of values.
        for( int val = 0; val <= 8; val++ )
            Console.WriteLine( "{0,3} - {1}", 
                val, ( (SingleHue)val ).ToString( ) );

        Console.WriteLine( 
            "\nAll possible combinations of values of an \n" +
            "Enum with FlagsAttribute:\n" );

        // Display all possible combinations of values.
        // Also display an invalid value.
        for( int val = 0; val <= 8; val++ )
            Console.WriteLine( "{0,3} - {1}", 
                val, ( (MultiHue)val ).ToString( ) );
    } 
} 

/*
This example of the FlagsAttribute attribute
generates the following output.

All possible combinations of values of an
Enum without FlagsAttribute:

  0 - Black
  1 - Red
  2 - Green
  3 - 3
  4 - Blue
  5 - 5
  6 - 6
  7 - 7
  8 - 8

All possible combinations of values of an
Enum with FlagsAttribute:

  0 - Black
  1 - Red
  2 - Green
  3 - Red, Green
  4 - Blue
  5 - Red, Blue
  6 - Green, Blue
  7 - Red, Green, Blue
  8 - 8
*/

posted on 2007-12-16 22:10  volnet(可以叫我大V)  阅读(381)  评论(1编辑  收藏  举报

使用Live Messenger联系我
关闭