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

时间:2016-07-22 07:38:44

标签: c# inheritance properties interface

我有一个只读属性的接口

public interface IPerson
{
    string Name { get; }
}

和具体的课程......

public class Person : IPerson
{

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

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

我希望Name只能在此类的外部读取,但如何在具体类中设置它?

错误:无法将Person.Name分配给。

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

6 个答案:

答案 0 :(得分:9)

这与界面无关,您只是错误地声明了该属性。在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可以是私有的。

答案 1 :(得分:6)

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

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

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

答案 2 :(得分:5)

现在,您正在尝试通过阅读该物业来阅读该物业。不用说,这将导致无限循环。相反,您需要使用完整的自动属性或手动支持字段。

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

    public string Name { get; private set; }
}

答案 3 :(得分:4)

你只需要一个私人的二传手(前面的#6):

public class Person : IPerson
{

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

    public string Name { get; private set; }

}

答案 4 :(得分:3)

尝试使用accessors

private string _name;

public string Name
{
    get
    {
        return _name;
    }
}

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

答案 5 :(得分:1)

我希望Name仅在此类外部读取,但是如何在具体的类中设置

首先,让我们认识到:一个界面仅描述了一组public需求;它不会阻止我们实施 other 个公共成员,也不会限制我们创建私有成员的能力

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

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...

如果愿意,我们可以通过一种方法来访问私有设置器。通常这样做是为了使人的重命名非常有意(例如,在进行比较时,它可以防止意外分配)。如果客户端尝试person.Name = "Foo";,但他们可以编写person.RenameAs("Foo");

,则客户端会从编译器获得设计时错误。
    public void RenameAs(string newName)
    {
        // Potentially do some validation before setting the name
        if (IsValidName(newName)) Name = newName;
    }
}