C# attribute和Java annotation……

25 篇文章 0 订阅
Java与C#都从一开始就强调程序的模块化,所以写出来的程序不但包括代码逻辑,还包括类型信息等“元数据”。Java早期版本只支持有限的几种元数据,用户无法自定义新的元数据类型;后来者C#则从一开始就在支持内建attribute的同时支持用户定义的attribute,为程序在运行时提供更多信息。从Java 5开始,Java添加了一些内建元数据类型,并且开始以annotation的形式支持用户定义的元数据。这样,在Java和C#中,用户都可以通过元数据来扩展语言,为语言提供更丰富的语义。 

C#里要自定义attribute类型,可以直接或间接继承 System.Attribute 类,并通过 AttributeUsageAttribute 来指定attribute的应用范围,然后像定义普通的public类一样定义attribute的内容。 
指定应用范围的 AttributeTargets 有以下成员: 
MSDN 写道
AssemblyAttribute can be applied to an assembly.
ModuleAttribute can be applied to a module.
ClassAttribute can be applied to a class.
StructAttribute can be applied to a structure; that is, a value type.
EnumAttribute can be applied to an enumeration.
ConstructorAttribute can be applied to a constructor.
MethodAttribute can be applied to a method.
PropertyAttribute can be applied to a property.
FieldAttribute can be applied to a field.
EventAttribute can be applied to an event.
InterfaceAttribute can be applied to an interface.
ParameterAttribute can be applied to a parameter.
DelegateAttribute can be applied to a delegate.
ReturnValueAttribute can be applied to a return value.
GenericParameterAttribute can be applied to a generic parameter.
AllAttribute can be applied to any application element.

一个简单的attribute的例子: 

using System;

// define a custom attribute
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class LazyPopulateAttribute : Attribute {
    Type _propType;
    
    public LazyPopulateAttribute(Type propType) {
        _propType = propType;
    }
    
    public Type PropertyType {
        get { return _propType; }
    }
}


public class Singleton {
    static Singleton _instance;
    
    private Singleton() { }
    
    // use the custom attribute
    [LazyPopulate(typeof(Singleton))]
    public static Singleton Instance {
        get { return _instance; }
    }
}

static class Program {
    static void Main(string[] args) {
        var instance = Singleton.Instance;
        // ...
    }
}

上面的代码光是这么写的话,_instance没人赋过值,用起来显然有问题。但我们可以写一个程序在postbuild时分析程序集,提取出其中的attribute,并且让LazyPopulateAttribute指定的属性展开为典型的double-check初始化,Instance展开后应该变为: 

public static Singleton Instance {  
    get {  
        var instance = _instance;  
        if (null == instance) {  
            lock(_lockObj) { // _lockObj是应该生成的成员  
                  if (null == _instance) {  
                    _instance = instance = new Singleton();  
                }  
            }  
        }  
        return instance;  
    }  
}  

在运行时通过反射,PropertyInfo.GetCustomAttributes()就可以得到针对property的attribute信息。

Java方面,支持3种内建的annotation,包括@Override、@Deprecated、@SuppressWarnings。 
指定应用范围的ElementType枚举类型有以下成员: 

Javadoc 写道
ANNOTATION_TYPEAnnotation type declaration
CONSTRUCTORConstructor declaration
FIELDField declaration (includes enum constants)
LOCAL_VARIABLELocal variable declaration
METHODMethod declaration
PACKAGEPackage declaration
PARAMETERParameter declaration
TYPEClass, interface (including annotation type), or enum declaration

在Java中自定义annotation类型的方法很简单,跟定义接口类似。使用@interface关键字来声明annotation类型,然后像声明方法一样声明其中的成员。与定义接口不同的是,annotation类型的成员可以带有default默认值声明。

public @interface NotImplemented {  
    public enum Severity { CRITICAL, HIGH, MEDIUM, LOW, NONE }  
    Severity severity() default Severity.NONE;  
} 

要说C# attribute跟Java annotation有什么关系,相同点是它们都是元数据的载体,差别恐怕主要在于两者的可应用范围不同了。可以看到,两者受到C#和Java语言本身的差异的影响,可应用的范围已经有所不同,例如C#可以对程序集或者模块应用attribute,但不能对命名空间应用;Java可以对包应用annotation,但不能对例如说JAR文件之类的不属于Java语言本身所支持的组织范围应用。 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值