2

Possible Duplicate:
Class with indexer and property named “Item”

Just came across something I've not seen before and was wondering why this might be happening?

With the following class, I get the compiler error "Member with the same name is already declared" with respect to "Item" and "this[...]".

public class SomeClass : IDataErrorInfo 
{
    public int Item { get; set; }

    public string this[string propertyName]
    {
        get
        {
            if (propertyName == "Item" && Item <= 0)
            {
                return "Item must be greater than 0";
            }
            return null;
        }
    }

    public string Error
    {
        get { return null; }
    }
}

The compiler seems to think that this[...] and Item are using the same member name. Is this correct / normal? I am surprised I have not come across this before.

Community
  • 1
  • 1
Mike Rowley
  • 908
  • 9
  • 20
  • This is a duplicate. See the answer to this SO question: http://stackoverflow.com/questions/5110403/class-with-indexer-and-property-named-item. – Philipp Schmid Jul 15 '11 at 21:11

4 Answers4

8

When you define the indexer like this:

this[string propertyName]

It is compiled into the .Item property.

You can fix that with [System.Runtime.CompilerServices.IndexerName("NEW NAME FOR YOUR PROPERTY")] attribute to your indexer.

VMAtm
  • 27,943
  • 17
  • 79
  • 125
6

Yep. this[] compiles down to a property called Item by default. You can change that using the System.Runtime.CompilerServices.IndexerName attribute. (MSDN link)

dlev
  • 48,024
  • 5
  • 125
  • 132
2

It's normal. The C# language has the keyword "this" which is used to declare indexers, but in the compiled class, the get method for the indexer will be called "get_Item" (which is the cross-language convention in .NET). Since the compiler wants to give the same name to the getter for your Item property, it reports an error.

Kevin Watkins
  • 101
  • 1
  • 1
0

If you look at the IDataErrorInfo interface with IL code you will se

.class public interface abstract auto ansi IDataErrorInfo
{
    .custom instance void [mscorlib]System.Reflection.DefaultMemberAttribute::.ctor(string) = { string('Item') }
    .property instance string Error
    {
        .get instance string System.ComponentModel.IDataErrorInfo::get_Error()
    }

    .property instance string Item
    {
        .get instance string System.ComponentModel.IDataErrorInfo::get_Item(string)
    }

}

which does translate in C# to

public interface IDataErrorInfo
{
    // Properties
    string Error { get; }
    string this[string columnName] { get; }
}

So the reason is C# does hide some special method name behind the this syntax from you which does collide with the real method name used by the CLR.

Alois Kraus
  • 13,229
  • 1
  • 38
  • 64