我正在try 合并几个包.包含所有特定 struct 的UnitsNet,以及Microsoft Mvvm,该Mvvm为INotifyPropertyChanged的属性提供了大约Set<T>个函数.这Set<T>个函数中有一个需要IEqualityComparer<T>.

我知道我的QuantityEqualityComparer分与UnitsNet的每struct分是一样的.我看到IEqualityComparer<in T>是反变的.所以我想我明白下面的例子应该是可能的.但在这种通用方法中不接受等式比较器.

似乎不可能投_barIQuantity,我也试着打Set<IQuantity>().但这两条语句都会被编译器拒绝.

我现在实现的解决方案是一种缓存机制,它将通过反射创建特定的IEqualityComparer,但这似乎有些过头了.

你可以在这里找到一个例子:https://dotnetfiddle.net/N7vfc9

using System;
using System.Collections.Generic;
                    
public class Program
{
    private static Length _bar;
    
    public static void Main()
    {
        // Error: cannot convert from QuantityEqualityComparer to IEqualityComparer<Length>
        Set(ref _bar, new Length(), new QuantityEqualityComparer());
    }
    
    // from Mvvm
    public static bool Set<T>(ref T field, T value, IEqualityComparer<T> comparer)
    {
        return true;
    }
}
            
public class QuantityEqualityComparer : IEqualityComparer<IQuantity>
{
    public bool Equals(IQuantity x, IQuantity y)
    {
        // custom implementation
    }
    
    public int GetHashCode(IQuantity obj)
    {
        // custom implementation
    }
}

// from UnitsNet
public interface IQuantity
{
}

public struct Length : IQuantity, IEquatable<Length>
{
    public bool Equals(Length other)
    {
        return true;
    }
}

推荐答案

调用QuantityEqualityComparer.Equals方法需要对长度 struct 进行装箱,这就是逆变换失败的原因.

差异仅适用于引用类型;如果为变量类型参数指定值类型,则该类型参数对于生成的构造类型是不变的.

source

虽然这可能与你已经拥有的相似,但这是我要开始的;

public static bool Set<T>(ref T field, T value)
    where T:IQuantity
=> Set<T>(ref field, value, QuantityEqualityComparer<T>.Instance);

public class QuantityEqualityComparer<T> : IEqualityComparer<T>
where T:IQuantity
{
    public static QuantityEqualityComparer<T> Instance = new();
    //...
}

然后使用反射或表达式树调用这个.Set<T>方法.

Csharp相关问答推荐

如何保持主摄像头视角保持一致?

有没有一种方法可以在包含混合文本的标签中嵌入超链接?

一种安全的方式来存储SSH凭证(MAUI/C#应用程序)

使用客户端密钥为Fabric Rest API生成令牌

无法解析数据库上下文的服务

安装附加的. exe与Visual Studio

ITypeLib2.GetLibStatistics()在C#中总是抛出AccessViolationException

在一个模拟上设置一个方法,该模拟具有一个参数,该参数是一个numc函数表达式

如何删除文件的基础上嵌入的时间戳嵌入文件名

在路由中使用枚举

UWP中的任务和界面

CS1660无法将lambda表达式转换为类型INavigationBase,因为它不是委托类型

调用Task.Run()与DoSomethingAsync()有什么不同?

在使用StringBuilder时,如何根据 colored颜色 设置为richTextBox中的特定行着色?

链接到字典字符串.拆分为(.Key,.Value)

用于ASP.NET核心的最小扩展坞

如果所有";async任务方法()";调用都返回Task.FromResult()-是否同步执行?

S,在.NET核心控制台应用程序中,AddScope和AddSingleton有什么不同?

使用生产环境调试我的应用程序的快速方法

同时通过多个IEumable<;T&>枚举