我有一个名为汽车的类,具有属性颜色和年份。 我正在尝试创建一个更新方法,以便它仅更新提供的参数,可以是颜色、年份或两者,但如果没有给出参数,则汽车对象仍保留旧属性。
这就是我所做的
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;}
}
在回答你的问题之前(我将在最后回答),你将一些不同的概念混合在一起,这将有助于首先分离和理解。
您的
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
方法。
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的内容,看看如何做到这一点。 希望有帮助。