C# 如何使字段在课外只读

C# 如何使字段在课外只读,c#,.net,access-modifiers,C#,.net,Access Modifiers,我有以下课程(示例): 创建dog对象后,它应该计算出牙齿的数量。我希望能够访问该值,而不必在类本身之外修改它 Dog d = new Dog(); int dogTeeth = d.numberOfTeeth; //this should be possible d.numberOfTeeth = 10; //this should not 然而,我不知道哪个访问修饰符会让我这么做。我尝试了以下所有方法: 如果我将numberoftooth设为私有,我将无法访问它。 如果我将numberof

我有以下课程(示例):

创建dog对象后,它应该计算出牙齿的数量。我希望能够访问该值,而不必在类本身之外修改它

Dog d = new Dog();
int dogTeeth = d.numberOfTeeth; //this should be possible
d.numberOfTeeth = 10; //this should not
然而,我不知道哪个访问修饰符会让我这么做。我尝试了以下所有方法:

如果我将
numberoftooth
设为私有,我将无法访问它。
如果我将
numberoftooth
设置为受保护的内部,我可以在类外更改此值。
如果我将
numberofteaths
设置为internal,我可以在类外更改此值。
如果我将
numberoftooth
设置为受保护的,我将无法访问它。
如果我将
numberoftooth
设置为public,我可以在类外更改此值。

我还尝试将其设置为只读,但无法在构造函数外部设置


有没有允许我这样做的访问修饰符?或者有其他方法来实现这种保护吗?

你不能这么做。可以将字段设置为只读,并创建一个返回其值的方法。还可以使用公共getter和受保护的setter创建自动属性:

public int NumberOfTeeth { get; protected set; }

使用专用setter创建属性:

public int NumberOfTeeth
{
 get; private set;
}

请注意,我将其更改为Pascal大小写,以符合大多数.NET样式的标准。

您应该将字段
设为私有
,并创建一个只读(无setter)
公共
属性:

public class Dog
{
    public int numberOfTeeth { get; private set; }

    public Dog() 
    {   
        countTeeth(); 
    }
}
public class Dog
{
    private int numberOfTeeth;
    public int NumberOfTeeth {get {return numberOfTeeth;}}

    public Dog() 
    { 
        countTeeth(); 
    }

    private void countTeeth()
    {
        this.numberOfTeeth = 5; //this dog has seen better days, apparently
    }
}

只是想澄清一下:
numberofteaths
在您的示例中是一个字段,而不是一个属性。@BrianRasmussen啊,您说得对。谢谢通过使用专用setter并在其中执行牙齿计数代码,可以避免使用单独的牙齿计算方法。这将使代码更清晰。EDIT D Stanley已经发布了我在这里评论的答案。@CoffeeMuncher不幸的是,我的“真实”代码相当复杂,所以我认为需要一个单独的方法。谢谢你的提示!我想,
counttooth()
只是为了解除私人访问的中心。它当然可以根据实际使用情况进行重构。@Mansfield您是否每次都添加逻辑以阻止计算?不在每次调用该方法时进行计算可能会提高效率;这一切都取决于它的复杂程度。@CoffeeMuncher方法是在构造函数中调用的,因此当对象被创建时。不幸的是,每次创建对象时都需要计算,并且它会根据类中字段的值进行更改。但是如果我没有使用基元类型呢?例如,让我们使用<代码>列表>代码>。是什么阻止其他类向其中添加/删除项?我知道我可以在这个特定的实例中使用
ReadOnlyCollection
,但我正在寻找一个通用的解决方案。@piter您可以向getter添加逻辑,以始终返回一个新集合-这样,如果调用方添加项,他们将向副本中添加项。但是,在这种情况下,我不会使用属性,而是使用GetXXXX方法-这通常是用于指示结果是副本的模式。@Pieter如果您想作为一个新问题提问,我很乐意为您提供一个示例:)
public class Dog
{
    private int numberOfTeeth;
    public int NumberOfTeeth {get {return numberOfTeeth;}}

    public Dog() 
    { 
        countTeeth(); 
    }

    private void countTeeth()
    {
        this.numberOfTeeth = 5; //this dog has seen better days, apparently
    }
}