gpt4 book ai didi

没有重复的 C# 不可变和可变类型

转载 作者:行者123 更新时间:2023-11-30 22:16:00 27 4
gpt4 key购买 nike

鉴于以下可变和不可变类型的实现,有没有办法避免重复代码(主要是重复属性)

我希望默认使用不可变类型,除非需要可变类型(例如,绑定(bind)到 UI 元素时)。

我们正在使用 .NET Framework 4.0,但计划很快切换到 4.5。

public class Person {
public string Name { get; private set; }
public List<string> Jobs { get; private set; } // Change to ReadOnlyList<T>
public Person() {}
public Person(Mutable m) {
Name = m.Name;
}
public class Mutable : INotifyPropertyChanged {
public string Name { get; set; }
public List<string> Jobs { get; set; }
public Mutable() {
Jobs = new List<string>();
}
public Mutable(Person p) {
Name = p.Name;
Jobs = new List<string>(p.Jobs);
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) {
// TODO: implement
}
}
}

public class Consumer {
public Consumer() {
// We can use object initializers :)
Person.Mutable m = new Person.Mutable {
Name = "M. Utable"
};
// Consumers can happily mutate away....
m.Name = "M. Utated";
m.Jobs.Add("Herper");
m.Jobs.Add("Derper");

// But the core of our app only deals with "realio-trulio" immutable types.

// Yey! Have constructor with arity of one as opposed to
// new Person(firstName, lastName, email, address, im, phone)
Person im = new Person(m);
}
}

最佳答案

我做了一些东西来满足你最近的要求(使用 T4 模板),所以这是绝对可能的:

https://github.com/xaviergonz/T4Immutable

例如,给定这个:

[ImmutableClass(Options = ImmutableClassOptions.IncludeOperatorEquals)]
class Person {
private const int AgeDefaultValue = 18;

public string FirstName { get; }
public string LastName { get; }
public int Age { get; }

[ComputedProperty]
public string FullName {
get {
return FirstName + " " + LastName;
}
}
}

它会在单独的部分类文件中自动为您生成以下内容:

  • 一个构造函数,例如 public Person(string firstName, stringlastName, int age = 18) 将初始化值。
  • Equals(object other) 和 Equals(Person other) 的有效实现。它还会为您添加 IEquatable 接口(interface)。在职的operator== 和 operator!= 的实现
  • GetHashCode() 的有效实现更好的 ToString() 输出如“Person { FirstName=John, LastName=Doe, Age=21 }”
  • Person With(...) 方法,可用于生成具有 0 个或多个属性更改的新不可变克隆(例如 var janeDoe = johnDoe.With(firstName: "Jane", age: 20)

所以它会生成这个(排除一些冗余属性):

using System;

partial class Person : IEquatable<Person> {
public Person(string firstName, string lastName, int age = 18) {
this.FirstName = firstName;
this.LastName = lastName;
this.Age = age;
_ImmutableHashCode = new { this.FirstName, this.LastName, this.Age }.GetHashCode();
}

private bool ImmutableEquals(Person obj) {
if (ReferenceEquals(this, obj)) return true;
if (ReferenceEquals(obj, null)) return false;
return T4Immutable.Helpers.AreEqual(this.FirstName, obj.FirstName) && T4Immutable.Helpers.AreEqual(this.LastName, obj.LastName) && T4Immutable.Helpers.AreEqual(this.Age, obj.Age);
}

public override bool Equals(object obj) {
return ImmutableEquals(obj as Person);
}

public bool Equals(Person obj) {
return ImmutableEquals(obj);
}

public static bool operator ==(Person a, Person b) {
return T4Immutable.Helpers.AreEqual(a, b);
}

public static bool operator !=(Person a, Person b) {
return !T4Immutable.Helpers.AreEqual(a, b);
}

private readonly int _ImmutableHashCode;

private int ImmutableGetHashCode() {
return _ImmutableHashCode;
}

public override int GetHashCode() {
return ImmutableGetHashCode();
}

private string ImmutableToString() {
var sb = new System.Text.StringBuilder();
sb.Append(nameof(Person) + " { ");

var values = new string[] {
nameof(this.FirstName) + "=" + T4Immutable.Helpers.ToString(this.FirstName),
nameof(this.LastName) + "=" + T4Immutable.Helpers.ToString(this.LastName),
nameof(this.Age) + "=" + T4Immutable.Helpers.ToString(this.Age),
};

sb.Append(string.Join(", ", values) + " }");
return sb.ToString();
}

public override string ToString() {
return ImmutableToString();
}

private Person ImmutableWith(T4Immutable.WithParam<string> firstName = default(T4Immutable.WithParam<string>), T4Immutable.WithParam<string> lastName = default(T4Immutable.WithParam<string>), T4Immutable.WithParam<int> age = default(T4Immutable.WithParam<int>)) {
return new Person(
!firstName.HasValue ? this.FirstName : firstName.Value,
!lastName.HasValue ? this.LastName : lastName.Value,
!age.HasValue ? this.Age : age.Value
);
}

public Person With(T4Immutable.WithParam<string> firstName = default(T4Immutable.WithParam<string>), T4Immutable.WithParam<string> lastName = default(T4Immutable.WithParam<string>), T4Immutable.WithParam<int> age = default(T4Immutable.WithParam<int>)) {
return ImmutableWith(firstName, lastName, age);
}

}

项目页面中还介绍了一些其他功能。

PS:如果你想要一个包含其他不可变对象(immutable对象)列表的属性,只需添加:

public ImmutableList<string> Jobs { get; }

关于没有重复的 C# 不可变和可变类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17717252/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com