How to Resolve Error "CS0415: The 'IndexerName' attribute is valid only on an indexer that is not an explicit interface member declaration" in C#
The Compiler Error CS0415 is an attribute usage error. The message reads: "The 'IndexerName' attribute is valid only on an indexer that is not an explicit interface member declaration."
In C#, Indexers allow objects to be indexed like arrays (e.g., myObject[0]). Under the hood, the compiler generates a property named Item for this indexer. The [IndexerName] attribute allows you to rename this underlying property. However, when you implement an interface explicitly (hiding the member from the class's public API), the underlying name is strictly controlled by the interface contract. Therefore, you cannot apply a custom name to an explicit implementation.
This guide explains why this conflict exists and how to properly apply this attribute.
Understanding IndexerName and Explicit Interfaces
[IndexerName("Name")]: By default, C# compiles indexers into a property namedItem. This attribute allows you to change that internal name (e.g., toValueorEntry). This is often done for interoperability with languages that don't support indexer syntax directly.- Explicit Interface Implementation: This creates a member that is only accessible when the object is cast to the Interface type (e.g.,
((IList)myObj)[0]).
When you implement an interface explicitly, you are fulfilling a specific contract defined by that interface. The interface metadata already dictates the name of the indexer property. You cannot override this metadata name within the implementing class using an attribute.
Scenario: The Invalid Attribute Usage
This error occurs when you apply [IndexerName] to an indexer defined with the Interface.this[...] syntax.
Example of error:
using System.Runtime.CompilerServices;
public interface IDataStore
{
string this[int index] { get; set; }
}
public class MyStore : IDataStore
{
private string[] _data = new string[10];
// ⛔️ Error CS0415: The 'IndexerName' attribute is valid only on an indexer
// that is not an explicit interface member declaration.
// You cannot rename 'IDataStore.Item' to 'MyItem' here.
[IndexerName("MyItem")]
string IDataStore.this[int index]
{
get { return _data[index]; }
set { _data[index] = value; }
}
}
Solution 1: Remove the Attribute (Recommended)
Since explicit interface members are hidden from the class's public surface area, the internal property name usually does not matter to consumers of your class. The simplest fix is to remove the attribute. The indexer will use the default name defined by the interface (usually Item).
Solution:
using System.Runtime.CompilerServices;
public interface IDataStore
{
string this[int index] { get; set; }
}
public class MyStore : IDataStore
{
private string[] _data = new string[10];
// ✅ Correct: Attribute removed.
// This implements the interface correctly using the default metadata name.
string IDataStore.this[int index]
{
get { return _data[index]; }
set { _data[index] = value; }
}
}
Solution 2: Use Implicit Implementation
If you specifically need the underlying property to have a custom name (perhaps for reflection or COM interop purposes), you must make the indexer a public member of the class (Implicit Implementation).
Public members belong to the class itself, so you have full control over their metadata attributes.
Solution: change the signature from IDataStore.this to public string this.
using System.Runtime.CompilerServices;
public interface IDataStore
{
string this[int index] { get; set; }
}
public class MyStore : IDataStore
{
private string[] _data = new string[10];
// ✅ Correct: This is now a standard public member.
// We can rename the underlying property to "MyCustomName".
[IndexerName("MyCustomName")]
public string this[int index]
{
get { return _data[index]; }
set { _data[index] = value; }
}
}
By making it public, MyStore instances can now be indexed directly (store[0]) without casting to IDataStore first.
Conclusion
CS0415 is a metadata conflict error.
- Check the Declaration: Are you using explicit syntax (
Interface.this)? - Check the Attribute: Are you using
[IndexerName]? - Decide:
- If you want to hide the member (Explicit), remove the attribute.
- If you want to rename the member (Attribute), make the indexer public.