C# 设置在具体类的接口中定义的只读属性

C# 设置在具体类的接口中定义的只读属性,c#,inheritance,properties,interface,C#,Inheritance,Properties,Interface,我有一个只读属性的接口 public interface IPerson { string Name { get; } } 和一个具体的类 public class Person : IPerson { public Person() { Name = "Person"; } public string Name { get { return Name;

我有一个只读属性的接口

public interface IPerson
{
    string Name { get; }
}
和一个具体的类

public class Person : IPerson
{

    public Person()
    {
        Name = "Person";
    }

    public string Name
    {
        get
        {
            return Name;
        }
    }
}
我希望名称只能在这个类的外部读取,但如何在具体类中设置它呢

错误:无法为人员分配名称


如何在Person类中设置此属性的值?

您可以使用私有属性来保存该值

public class Person : IPerson
{
    private string _name;
    public Person()
    {
        _name = "Person";
    }

    public string Name
    {
        get
        {
            return _name;
        }
    }
}

这与接口无关,只是错误地声明了属性。在C#6中,可以创建如下只读属性:

public class Person : IPerson
{
    public Person()
    {
        Name = "Person";
    }

    public string Name { get; }
}
在早期版本中,您可以使用只读备份字段,可以设置:

public class Person : IPerson
{
    private readonly string _name;

    public Person()
    {
        _name = "Person";
    }

    public string Name
    {
        get { return _name; }
    }
}
注意,接口只需要属性有一个getter,实现不必是只读的。如果有理由修改该值,则可以添加setter:

public class Person : IPerson
{
    public Person()
    {
        Name = "Person";
    }

    public string Name { get; set; }
}
如果您只需要在类中更改值,则setter可以是私有的。

尝试使用:


然后,您可以在任何方法或构造函数中设置
\u name
的值。

现在,您正试图通过读取属性来读取属性。不用说,这将导致一个无休止的循环。相反,您需要使用完整的自动属性,或者手动备份字段

public class Person : IPerson
{
    public Person()
    {
        Name = "Person";
    }

    public string Name { get; private set; }
}

您只需拥有一个私人setter(c#6之前):

我希望名称只能在这个类的外部读取,但是如何在具体类中设置它呢

首先,让我们认识到:一个接口只描述一组
公共
需求
;它不会阻止我们实现其他公共成员,也不会限制我们创建私有成员的能力

因此,要使属性从类内部可写但在其他地方为只读,我们可以使用
private
范围声明
set
方法:

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...
如果我们愿意,我们可以通过一个方法来访问私有setter。这样做通常是为了使一个人的重命名非常有目的(例如,当打算进行比较时,它可以防止意外的赋值)。如果客户端尝试
person.Name=“Foo”,则会从编译器中获得设计时错误person.RenameAs(“Foo”)


但是,这仅在属性确实应该是只读的情况下才起作用。OP的描述中不清楚他是否想稍后在
Person
类中更改值。谢谢-我现在明白了这是怎么回事。我不需要在编写后更改名称(在本例中),但如果我更改了,那么我将使用accessors。我现在意识到,我可以简单地排除返回名称;咬了一口,就得到了;
public class Person : IPerson
{

    public Person()
    {
        Name = "Person";
    }

    public string Name { get; private set; }

}
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...
    public void RenameAs(string newName)
    {
        // Potentially do some validation before setting the name
        if (IsValidName(newName)) Name = newName;
    }
}