更新对象方法,带有可选参数

问题描述 投票:0回答:1

我有一个名为汽车的类,具有属性颜色和年份。 我正在尝试创建一个更新方法,以便它仅更新提供的参数,可以是颜色、年份或两者,但如果没有给出参数,则汽车对象仍保留旧属性。

这就是我所做的

  internal class car
   {

       public car()
       {

       }

public car Update(string arg_color = null, int? arg_year = null)
{

//Problem is here, I want it to keep the old color when I use SomeOldCar.Update(*DifferentYear*)

    car NewCar = new car();
    NewCar.color = arg_color;

    NewCar.year = arg_year;

    return car
}

public string? color {get;set;}
public int? year {get;set;}
}
c# object methods
1个回答
0
投票

在回答你的问题之前(我将在最后回答),你将一些不同的概念混合在一起,这将有助于首先分离和理解。

1.如何更新对象的属性

直接使用其属性

您的

color
year
属性都有 get 和 set 方法。这意味着任何人都可以更新它们,甚至不需要您的
Update
方法,就像这样:

Car myCar = new Car();

myCar.Color = "Red";

使用更新方法

像您一样拥有 Update 方法是完全有效的。当在允许分配新值之前需要执行重要的验证(即检查)逻辑时,通常会使用此方法。重写您的

car
类来演示检查:

public class Car
{
    public string? Color { get; private set; }
    public int? Year { get; private set; }

    public void Update(string? arg_color = null, int? arg_year = null)
    {
        // Prevent assigning a combination of values that we know are wrong.
        if (arg_color != "Black" && arg_year < 1910)
        {
            throw new InvalidOperationException("All cars before 1910 were black");
        }

        // Or else, assign the values.
        Color = arg_color;
        Year = arg_year;
    }
}

您还会注意到,我已将属性

Color
Year
转换为
private set
。这是因为我们使用的是 Update 方法,因此没有必要公开使用
set
。我们故意阻止任何人直接设置这些值,以便他们被迫使用我们的
Update
方法。现在您可以这样设置值:

myCar.Update("Blue", 2024);

myCar.Color = "Blue"; // <- this no longer works because we have a private setter. The compiler will not allow it.

在上述方法之间进行选择

通常,您将 拥有 Update 方法, 您将拥有属性的 set

 方法。混合两者是没有意义的,它会让您(和其他开发人员)感到困惑,因为这让他们不清楚是否应该选择 
Update
 还是 
set

    如果您有一个没有验证逻辑并且基本上只有一堆值的类:使用
  • set
     方法。
  • 如果您有一个类,其中包含逻辑,或者在更新值时有复杂的行为:请改为使用方法。
2.创建新对象

错误的方式(你的代码)

您有点混淆的第二个概念是:

public Car Update(string arg_color = null, int? arg_year = null) { Car newCar = new Car(); // ...snipped code for brevity... return newCar; }
您在这里所做的是创建一个全新的汽车对象并将其返回。您根本

没有修改或更新原车。

因此,

Update方法和上述

set
方法都不会改变您的汽车。你实际上是在创造一辆新车。不更新一个了。如果您在代码中尝试这样做,您会看到这种情况发生:
Car thisCar = new Car() { Color = "Red", Year = 2024 };

thisCar.Update("Blue", 2000);

Console.WriteLine(thisCar.Year); // <- this will still be "2024"
Console.WriteLine(thisCar.Color); // <- this will still be "Red"

所以看起来一切都没有改变。事实上,你在
Update

中所做的是创造一辆全新的汽车,而没有意识到它具有新的价值。你可以通过尝试这个来证明这一点:

Car thisCar = new Car() { Color = "Red", Year = 2024 };
Car newCar = thisCar.Update("Blue", 2000);

Console.WriteLine(thisCar.Year); // <- this will still be "2024"
Console.WriteLine(thisCar.Color); // <- this will still be "Red"

Console.WriteLine(newCar.Year); // <- this will be "2000"
Console.WriteLine(newCar.Color); // <- this will be "Blue"

这是一个奇怪的组合。您有一个 Update 方法,它实际上并不更新对象,而是返回新的内容。

一种有效的方法(以及你问题的一个可能答案)

一个有效的编码模式,您可以在其中更改一些数据(例如修改颜色),但安全地保持原始数据完好无损,并返回一个新副本。在 C# 中,这是通过 record 完成的,看起来像这样:

public record Car(string? color, int? year);

这与您的 
Car

课程基本相同,但要短得多。它有两个属性和(正如您接下来将看到的)更新它的方法。

那么现在,终于回答你的问题了:这里你可以拿一个

Car

,使用

with
关键字修改some属性,其他属性都向前复制:
Car redCar = new Car("Red", 2024);
Car blueCar = redCar with { Color = "Blue" };

Console.WriteLine(redCar.Color); // <- this will still be Red
Console.WriteLine(blueCar); // <- this will now be Blue, but also 2024

请注意,如果您想进行验证,就像我之前的 Update 示例一样,那么您仍然可以向记录添加 Update 方法。我不会在这里举一个例子,但你可以阅读一些关于 
record

^1
的内容,看看如何做到这一点。 希望有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.