简体   繁体   English

C#当已经实现了getter时,对象的setter的目的是什么?

[英]C# What is the purpose of a setter for an object when a getter is already implemented?

If there's a class which has a getter for an object, when the getter returns the object you can modify this object outside of its own class container, and this changes will be reflected when you read the object later with the getter again; 如果有一个具有对象的getter的类,当getter返回对象时,您可以在其自己的类容器之外修改该对象,并且稍后当您再次使用getter读取该对象时,将反映此更改。 so, I can't see the goal to set a setter for the object when the getter let me to read and modify the object as well. 所以,当getter让我读取和修改对象时,我看不到为对象设置setter的目标。

Example: You have a class called CashRegister and this class has an object called queue, if you read queue by means of a CashRegister's getter you can modify queue from the MainClass and the next time you invoke the CashRegister's getter the modifications previously made in MainClass will be present. 示例:您有一个名为CashRegister的类,并且此类有一个名为queue的对象,如果您通过CashRegister的getter读取队列,则可以从MainClass修改队列,并在下次调用CashRegister的getter时,先前在MainClass中进行的修改将出席。 By the way CLI.PrintAndJump() prints the content of a queue. 顺便说一句,CLI.PrintAndJump()打印队列的内容。

class MainClass
{
    static void Main(string[] args)
    {
        Queue<int> tmpQueue, tmpQueue2;
        CashRegister aCashRegister = new CashRegister();

        tmpQueue = aCashRegister.GetCoinValues();
        CLI.PrintAndJump(tmpQueue);

        tmpQueue.Enqueue(10);

        tmpQueue2 = aCashRegister.GetCoinValues();
        CLI.PrintAndJump(tmpQueue2);
    }
}

class CashRegister
{
    Queue<int> coinValues = new Queue<int>(1);

    public Queue<int> GetCoinValues()
    {
        return (coinValues);
    }
}

Output: 输出:

1 1

1, 10 1,10

In a nutshell, if you need to modify the object queue, you don't need to set a setter for it (Is this method a good practice?), but what if I want the object to remain immutable? 简而言之,如果你需要修改对象队列,你不需要为它设置一个setter(这个方法是一个好习惯吗?),但如果我希望对象保持不变,该怎么办?

Thanks. 谢谢。

In the context of C#, we typically talk about "setter" and "getter" methods in relation to a property, so it's kind of odd that your code example doesn't include any properties. 在C#的上下文中,我们通常会讨论与属性相关的“setter”和“getter”方法,因此您的代码示例不包含任何属性有点奇怪。 But, let's ignore that for a moment, and assume that you might have a corresponding SetCoinValues() method. 但是,让我们暂时忽略它,并假设你可能有一个相应的SetCoinValues()方法。

The reason for such a method would be if you want to replace the entire Queue<int> object. 这种方法的原因是如果要替换整个 Queue<int>对象。 There is a difference between modifying the Queue<int> object itself, which you can do with only a getter method, and replacing the Queue<int> object with a whole new one, which would require a setter method. 修改Queue<int>对象本身(只能使用getter方法)和 Queue<int>对象替换为全新对象(需要setter方法)之间存在差异。

Why one might want to do this varies. 为什么人们可能想这样做会有所不同。 It depends on the exact circumstance. 这取决于具体情况。 And I think it's less likely one might want to replace a queue object, than say some other collection type (like an array or a list), or some other complex type other than a collection. 而且我认为人们不太可能想要替换队列对象,而不是说其他​​集合类型(如数组或列表),或者除了集合之外的其他一些复杂类型。 But it could still happen. 但它仍然可能发生。

Examples of complex types which are used as property values, or in terms of the non-property scenario, might have both a getter and setter method, include System.Windows.Media.Pen.DashStyle and System.Diagnostics.Process.StartInfo . 用作属性值的复杂类型的示例,或者就非属性场景而言,可能同时具有getter和setter方法,包括System.Windows.Media.Pen.DashStyleSystem.Diagnostics.Process.StartInfo The DashStyle object itself even has properties for setting and getting complex values, including the Dashes property, which is a collection of Double values. DashStyle对象本身甚至具有用于设置和获取复杂值的属性,包括Dashes属性,它是Double值的集合。

I mention these to emphasize that this really has nothing at all to do with mutable vs. immutable. 我提到这些强调的是,这真的有什么没有做与可变与不可变的。 Both DashStyle and ProcessStartInfo are mutable types, but we still have properties which reference objects of those types and which have setter methods in addition to a getter. DashStyleProcessStartInfo都是可变类型,但我们仍然具有引用这些类型的对象的属性,并且除了getter之外还具有setter方法。

The question of mutability (which seems to be the emphasis of the other answer ) is a red herring, and will only distract you from what is really going on. 可变性问题(这似乎是另一个答案的重点)是一个红色的鲱鱼,只会分散你的注意力。 The real point is that, even with mutable, complex types, there are times when you want to be able to replace the entire object, rather than modifying the object currently being held. 真正的问题是,即使是可变的复杂类型,有时您希望能够替换整个对象,而不是修改当前持有的对象。 In those cases, you need a setter method, so that you can change the actual reference for the property, instead of modifying the object the property refers to. 在这些情况下,您需要一个setter方法,以便您可以更改属性的实际引用,而不是修改属性引用的对象。

First of all, this is C#, not Java. 首先,这是C#,而不是Java。 In C#, we do not write getters and setters; 在C#中,我们不编写getter和setter; we use properties instead. 我们改用属性。 So, GetXyz() methods in C# are usually not getters, and they are very rarely paired with SetXyz() methods. 因此,C#中的GetXyz()方法通常不是 getter,并且很少与SetXyz()方法配对。 For example, think of ICollection.GetLength() . 例如,想一想ICollection.GetLength() Once we have established that, let's move on. 一旦我们确定了这一点,让我们继续前进。

Read-write properties are primarily used for immutable values, an example of which are primitives. 读写属性主要用于不可变值,其中一个示例是基元。 I hope you understand that you cannot get for example an int , change its value, and expect the value held by the containing object to also change. 我希望你明白你不能得到例如一个int ,改变它的值,并期望包含对象所持有的值也会改变。 You have to put it back. 你必须把它还掉。 And for this you need a writable property. 为此你需要一个可写属性。 But you have anticipated that, because in your question you are talking about objects. 但是你已经预料到了,因为在你的问题中你正在谈论对象。

Primitives are not the only entities that you cannot modify; 基元不是您无法修改的唯一实体; there exist plenty of immutable struct s and class es that behave the same way. 存在大量不可变的structclass es,它们的行为方式相同。 If a property returns to you an object that simply does not offer any methods that you could use to alter its state, the only thing you can do is create a different instance of that object, and put it back in the containing object, for which of course you will need a writable property. 如果属性向您返回一个对象,该对象根本不提供可用于更改其状态的任何方法,那么您唯一能做的就是创建该对象的不同实例,并将其放回到包含对象中,当然你需要一个可写的财产。

So, writable properties are necessary for writing back immutable entities. 因此,写入不可变实体需要可写属性。

When it comes to mutable objects, you are right, it does not make much sense to have a read-write property, because once you obtain a reference to the mutable object you can mutate it to your heart's content without ever having to "set" it back. 当谈到可变对象时,你是对的,拥有读写属性没有多大意义,因为一旦你获得了对可变对象的引用,你就可以将它改变为你内心的内容,而不必“设置”回来了。 For this reason, you will rarely see a setter for a mutable. 出于这个原因,你很少会看到一个可变的setter。 But it happens some times. 但它有时会发生。 Peter Duniho covers an example of this in his answer. Peter Duniho在他的回答中举了一个例子。 (It is mainly done for performance/convenience reasons, and the implied agreement in these cases is that the containing object does not have ownership of the object that is being set into it.) (主要是出于性能/便利性的原因,在这些情况下隐含的协议是包含对象没有对其进行设置的对象的所有权。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM