如何使字符串的记录相等不区分大小写?

How to make records equality case-insensitive for strings?

提问人:DavWEB 提问时间:6/18/2021 最后编辑:DavWEB 更新时间:11/11/2022 访问量:965

问:

我真的很喜欢 C# 9 记录。但是,我找不到一种优雅而简洁的方式来实现这样的想法:

record MyKey(string Foo, int Bar);

[Fact]
public void ShouldEqualIgnoreCase()
{
    MyKey a = new("ID", 42);
    MyKey b = new("Id", 42);

    Assert.Equal(a, b);
}
C 字符串 相等 -9.0 C# 记录类型

评论

3赞 Eldar 6/18/2021
这回答了你的问题吗?C# 9 记录的自定义相等性检查
0赞 Felix Castor 6/18/2021
在检查相等性之前,可以应用于这两个字符串。.ToUpper()
0赞 DavWEB 6/18/2021
@FelixCastor我不想保留琴弦的大小写,所以我不能在将它们分配给唱片之前申请。.ToUpper()
1赞 DavWEB 6/18/2021
@Eldar您的链接有帮助,谢谢。但是,我对结果并不满意,不得不再次自己实现 Equals(和 GetHashCode)。因此寻找一个好的解决方案(也许没有)。
5赞 JonasH 6/18/2021
您是否考虑过制作“CaseInsensitiveString”类型?这样一来,您就可以在一个地方而不是每条记录中覆盖相等性比较。

答:

2赞 T1Space 11/11/2022 #1

只需使用 ValueObjects 而不是基元。正如 JonasH 已经说过的那样。

创建一个名为“CaseInsensitiveString”的新类,用于实现 IEquatable。然后,该记录将使用 Equals 方法。

像这样的东西:

    public readonly struct CaseInsensitiveString : IEquatable<CaseInsensitiveString>
    {
        public readonly String StringValue;

        public CaseInsensitiveString( string value )
        {
            StringValue = value;
        }

        public bool Equals( CaseInsensitiveString other)
        {
            return string.Equals( StringValue, other.StringValue, StringComparison.InvariantCultureIgnoreCase );
        }

        public static implicit operator string( CaseInsensitiveString h ) => h.StringValue;
        public static implicit operator CaseInsensitiveString( string s ) => new CaseInsensitiveString(s);
    }

由于隐式运算符,您可以只使用字符串:

record MyKey(CaseInsensitiveString Foo, int Bar);
...
var a = new MyKey("ID", 42 );

参见:https://wiki.c2.com/?PrimitiveObsession'

评论

1赞 Dai 11/11/2022
C2 文章只是 Java 人员的重新发明(如果不是重新发现......来自 FP 的细化类型...- 无论如何,根据我的经验,我发现细化类型应该最小化它们的开销(因为它们没有/不应该有自己的任何可变状态)。在 C# 11 中,我们现在也可以使用。ValueObjectreadonly structreadonly record struct