Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explicit implementation of an interface using a getter-only auto-property (C# 6 feature)

Tags:

Using automatic properties for explicit interface implementation was not possible in C# 5, but now that C# 6 supports getter-only auto-properties, this should be possible now, right?

Creating the auto-property succeeds in C# 6, but when trying to assign a value to it in the constructor, you have to cast this to the interface type first, since the implementation is explicit. But that's where both VS 2015 RC and VS Code 0.3.0 display the error that can be seen in the comment:

using static System.Console;

namespace ConsoleApp
{
    public interface IFoo { string TestFoo { get; } }

    public class Impl : IFoo
    {
        // This was not possible before, but now works.
        string IFoo.TestFoo { get; }

        public Impl(string value)
        {
            // ERROR: Property or indexer 'IFoo.TestFoo' cannot be assigned to -- it is read only.
            ((IFoo)this).TestFoo = value;
        }
    }

    public class Program
    {
        // Yes, not static. DNX supports that (for constructor DI).
        public void Main(string[] args)
        {
            IFoo foo = new Impl("World");

            WriteLine($"Hello {foo.TestFoo}");
            ReadKey(true);
        }
    }
}

Note: I updated the original question that set a constant value to TestFoo. In my real-world scenario, the value comes from an object that is injected into the constructor. The answer by Daniel A. White is excellent if the value returned by the property can be set at initialization.

It says:

Property or indexer 'IFoo.TestFoo' cannot be assigned to -- it is read only.

Is there a way around this, or do I still have to use properties with backing fields for this case?

I am using Visual Studio 2015 RC and Visual Studio Code 0.3.0 with DNX451 1.0.0-beta4.

I have raised an issue over at the Roslyn GitHub page.


The possible duplicate is a question about the definition of an interface with a regular property that can be read. My question is about implementing such an interface explicitly using a new C# 6 feature, that, in theory, should make this possible. See the other question I linked in the first sentence for a similar one (but for C# 5, where getter-only auto-properties where not available yet).

like image 261
Nikon the Third Avatar asked Jun 05 '15 17:06

Nikon the Third


People also ask

What is an auto-implemented property in C#?

Auto-implemented properties declare a private instance backing field, and interfaces may not declare instance fields. Declaring a property in an interface without defining a body declares a property with accessors that must be implemented by each type that implements that interface.

Can an interface have properties C#?

Like a class, Interface can have methods, properties, events, and indexers as its members. But interfaces will contain only the declaration of the members. The implementation of the interface's members will be given by class who implements the interface implicitly or explicitly.

Can I inherit property from class to interface?

A class implements an interface, it does not inherit it. However, if you want to provide code for a derived class, you can just write a base class to contain it.

What is an interface in C# with example?

Beginning with C# 8.0, an interface may define a default implementation for members. An interface may not declare instance data such as fields, auto-implemented properties, or property-like events. By using interfaces, you can, for example, include behavior from multiple sources in a class.


2 Answers

You can get around this by using a read-only backing field for your explicitly implemented property. You can assign the injected value to the backing field within the constructor, the explicit property's get implementation will return it.

public class Impl : IFoo
{
    private readonly string _testFoo;

    string IFoo.TestFoo => _testFoo;

    public Impl(string value)
    {
        _testFoo = value;
    }
}
like image 119
Alex Wiese Avatar answered Oct 13 '22 03:10

Alex Wiese


I think you want this

string IFoo.TestFoo { get; } = "World";
like image 40
Daniel A. White Avatar answered Oct 13 '22 02:10

Daniel A. White