I have an interface with a read only property
public interface IPerson
{
    string Name { get; }
}
and a concrete class...
public class Person : IPerson
{
    public Person()
    {
        Name = "Person";
    }
    public string Name
    {
        get
        {
            return Name;
        }
    }
}
I want Name to be read only externally to this class, but how do I set it from within the concrete class?
Error: Person.Name cannot be assigned to.
How do I set the value of this property from within Person class?
This doesn't have anything to do with the interface, you're just declaring the property incorrectly. In C# 6, you can create a read-only property like this:
public class Person : IPerson
{
    public Person()
    {
        Name = "Person";
    }
    public string Name { get; }
}
In earlier versions, you can use a read-only backing field which you can set:
public class Person : IPerson
{
    private readonly string _name;
    public Person()
    {
        _name = "Person";
    }
    public string Name
    {
        get { return _name; }
    }
}
Note that the interface only requires the property has a getter, the implementation doesn't have to be read-only. You could add a setter if you had reason to modify the value:
public class Person : IPerson
{
    public Person()
    {
        Name = "Person";
    }
    public string Name { get; set; }
}
The setter could be private if you only needed to be able to change the value from within the class.
You can use a private property to hold the value.
public class Person : IPerson
{
    private string _name;
    public Person()
    {
        _name = "Person";
    }
    public string Name
    {
        get
        {
            return _name;
        }
    }
}
                        Right now, you're trying to read the property by reading the property. Needless to say, this will result in an endless loop. Instead, you either need to use full-blown auto-properties, or a manual backing field.
public class Person : IPerson
{
    public Person()
    {
        Name = "Person";
    }
    public string Name { get; private set; }
}
                        You simply have a private setter (pre c#6):
public class Person : IPerson
{
    public Person()
    {
        Name = "Person";
    }
    public string Name { get; private set; }
}
                        Try using accessors:
private string _name;
public string Name
{
    get
    {
        return _name;
    }
}
You can then set the value of _name inside any method or the constructor.
I want Name to be read only externally to this class, but how do I set it from within the concrete class
First of all, let's realize that: an interface only describes a set of public requirements; it does not prevent us from implementing other public members, nor does it limit our ability to create private members.
Therefore, to make a property writeable from inside the class but read-only elsewhere, we can declare the set method with private scope:
public class Person : IPerson
{
    // Name is read-only outside the class, but can be set internally
    public string Name { get; private set; } = "DefaultName";
    public Person() { }
    public Person(string name)
    {
        // Potentially do some validation before setting the name
        if (!IsValidName(name)) 
            throw new ArgumentException("Name cannot be null, empty, or whitespace.");
        Name = name;
    }
    private bool IsValidName(string name)
    {
        return !string.IsNullOrWhitespace(name);
    }
    // Continued below...
And if we want to, we can give access to the private setter through a method. This is often done in order to make the renaming of a person very intentional (for example, it prevents accidental assignments when a comparison was intended). The client will get a design-time error from the compiler if they try person.Name = "Foo"; but they can write person.RenameAs("Foo");
    public void RenameAs(string newName)
    {
        // Potentially do some validation before setting the name
        if (IsValidName(newName)) Name = newName;
    }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With