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