gpt4 book ai didi

c# - 在 C# : PostSharp or T4 templates? 中生成不可变值对象

转载 作者:太空狗 更新时间:2023-10-30 01:26:08 25 4
gpt4 key购买 nike

我厌倦了样板式不可变值对象代码。 PostSharp 或 T4 模板是否允许我进行以下转换?

输入:

public struct Name
{
public string FirstName;
public string LastName;
}

输出:

public struct Name : IEquatable<Name>
{
private readonly string firstName;
private readonly string lastName;

public string FirstName { get { return this.firstName; } }
public string LastName { get { return this.lastName; } }

public Name(string firstName, string lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}

public bool Equals(Name other)
{
return this.FirstName == other.FirstName && this.LastName == other.LastName;
}
public override bool Equals(object obj)
{
return obj is Name && this.Equals((Name)obj);
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
if (this.FirstName != null)
{
hash = hash * 29 + this.FirstName.GetHashCode();
}
if (this.LastName != null)
{
hash = hash * 29 + this.LastName.GetHashCode();
}
return hash;
}
}

public static bool operator==(Name a, Name b)
{
return a.Equals(b);
}
public static bool operator !=(Name a, Name b)
{
return !(a == b);
}
}

显然 PostSharp 需要一个 [MakeImmutable] 注释,这很好。我想要根据原始类型生成 classstruct 的选项。另请注意,GetHashCode 必须省略对值类型成员的 null 检查。

我相当确定这两种技术都具有这种能力,但我自己只是 PostSharp 方面/T4 模板的使用者,我不知道哪种技术更好或更容易完成这项任务。无论您给出哪个答案,我都会花一两天的时间学习足够的知识来完成这项工作:)。

最佳答案

我做了一些东西来满足你最近的要求(使用 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);
}

}

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

关于c# - 在 C# : PostSharp or T4 templates? 中生成不可变值对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5608149/

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