locked
Identifying the IndexerName attribute on an indexer property

    Question

  • Again with the attributes. :-) Is there a way to identify when this attribute has been applied to indexer properties?



    [IndexerName("Value")]
    public int this[int i]
    ...

     


    The Member.Attributes list is empty and Property.Flags has nothing. What I usually end up doing in these cases is look at the name property and do a string comparison of some sort. Here I grabbed the Type.DefaultMembers and looked for a NodeType.Property that had the name "Item". If I found one I'm assuming the IndexerName attribute was not applied. Of course someone could apply the attribute and pass in "Item" as the name but this is good enough for me. Any comments?
    Wednesday, October 05, 2005 3:57 PM

Answers

  • Excellent question! It turns out that IndexerNameAttribute never makes it in to the metadata. (Note that you that you can't find it using reflection eiher, see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemruntimecompilerservicesindexernameattributeclasstopic.asp).

    The compiler actually translates IndexerName in to the corresponding System.Reflection.DefaultMemberAttribute and applies it to the declaring type. For example, the above code would become (using fake C#-ish syntax to represent a named indexed property):



    [DefaultMember("Value")]
    class Foo {
         public int Value[int i] { ... }
    }

     


    In the absense of IndexerNameAttribute, the compiler still needs to identify the indexer using DefaultMemberAttribute and it provides "Item" by default. For example:



    class Foo {
          public int this[int i] { ... }
    }

     


    gets emitted as:



    [DefaultMember("Item")]
    class Foo {
         public int Item[int i] { ... }
    }

     


    As such, there is absolutely no distinction at the binary/metadata level between [IndexerName("Item")] and having no IndexerNameAttribute and so you cannot distinguish between these cases using FxCop. 

    Your approach is as close to detecting IndexerNameAttribute as you can get and so you should stick to it. I would go as far as to say that there's not much value in detecting IndexerName("Item") since it has no observable effect after compilation.

    Nick

     

    Thursday, October 06, 2005 4:10 AM

All replies

  • Excellent question! It turns out that IndexerNameAttribute never makes it in to the metadata. (Note that you that you can't find it using reflection eiher, see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemruntimecompilerservicesindexernameattributeclasstopic.asp).

    The compiler actually translates IndexerName in to the corresponding System.Reflection.DefaultMemberAttribute and applies it to the declaring type. For example, the above code would become (using fake C#-ish syntax to represent a named indexed property):



    [DefaultMember("Value")]
    class Foo {
         public int Value[int i] { ... }
    }

     


    In the absense of IndexerNameAttribute, the compiler still needs to identify the indexer using DefaultMemberAttribute and it provides "Item" by default. For example:



    class Foo {
          public int this[int i] { ... }
    }

     


    gets emitted as:



    [DefaultMember("Item")]
    class Foo {
         public int Item[int i] { ... }
    }

     


    As such, there is absolutely no distinction at the binary/metadata level between [IndexerName("Item")] and having no IndexerNameAttribute and so you cannot distinguish between these cases using FxCop. 

    Your approach is as close to detecting IndexerNameAttribute as you can get and so you should stick to it. I would go as far as to say that there's not much value in detecting IndexerName("Item") since it has no observable effect after compilation.

    Nick

     

    Thursday, October 06, 2005 4:10 AM
  • Thanks for the info. How many things in your source don't make it into the IL metadata? Is it documented exactly what all makes it into the IL? I guess the best resource would be to look at the Reflection documentation right?
    Thursday, October 13, 2005 2:01 PM
  • Reflection documentation can be helpful. I also recommend "Applied .NET Framework Programming" by Jeffrey Richter which describes some of these pseudo-custom attributes but also has a wealth of other good material about .NET fundamentals. Beyond that, the ECMA CLI specification has the details about how the special attributes map to flags in the metadata.

    Off the top of my head, I can think of the following pseudo-custom attributes (attributes which exist in source but are persisted differently to metadata), and here's how to find them from an FxCop rule.

    IndexerNameAttribute --> See above
    SerializedAttribute --> TypeNode.Flags & TypeFlags.Serialized
    NotSerializedAttribute --> Field.Flags.NotSerialized
    MethodImplAttribute --> Method.ImplFlags
    MarshalAsAttribute --> {Method,Parameter,Field}.MarshallingInformation, Method.ReturnTypeMarshallingInformation
    DllImportAttribute --> Method.Flags & MethodFlags.PInvokeImpl,

    I'm sure there are more, but hopefully this helps.

    Thanks
    Nick
    Thursday, October 13, 2005 5:21 PM