C#泛型中的类特定函数-可观察到的轻微mod-to-UWP模板

C#泛型中的类特定函数-可观察到的轻微mod-to-UWP模板,c#,generics,uwp,windows-template-studio,C#,Generics,Uwp,Windows Template Studio,我正在使用最新的UWP(和Windows Template Studio)方法构建一个应用程序。有一个聪明的班叫。 所以,这只是背景。我想修改第13行上的条件,以便Double的可忽略更改不会标记属性更改。所以,我扩充了第13行并创建了一个名为NegligibleChange的新函数 protected void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null) {

我正在使用最新的UWP(和Windows Template Studio)方法构建一个应用程序。有一个聪明的班叫。 所以,这只是背景。我想修改第13行上的条件,以便Double的可忽略更改不会标记属性更改。所以,我扩充了第13行并创建了一个名为NegligibleChange的新函数

    protected void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
    {
        if ((typeof(T) == typeof(double) && NegligibleChange(storage, value)) || Equals(storage, value))
        {
            return;
        }
        storage = value;
        OnPropertyChanged(propertyName);
    }

    private bool NegligibleChange(double  x, double y)
    {
        return Math.Abs(x - y) <= 1e-10;
    }

    public void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
受保护的无效集(ref T storage,T value,[CallerMemberName]string propertyName=null)
{
如果((typeof(T)=typeof(double)&&negiblechange(存储,值))| |等于(存储,值))
{
回来
}
储存=价值;
OnPropertyChanged(propertyName);
}
私有布尔可忽略更改(双x,双y)
{

返回Math.Abs(x-y)好吧,我对自己的问题有一个答案。你知道,泛型很难理解。如果以下不是处理这个问题的方法,请发表评论。需要的是添加一个非泛型版本的Set函数,该函数的输入签名为double。这样在运行时就没有附加条件了

    protected void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
    {
        if (Equals(storage, value))
        {
            return;
        }
        storage = value;
        OnPropertyChanged(propertyName);
    }
    protected void Set(ref double storage, double value, [CallerMemberName]string propertyName = null)
    {
        if (NegligibleChange(storage, value))
        {
            return;
        }
        storage = value;
        OnPropertyChanged(propertyName);
    }

    private bool NegligibleChange(double  x, double y)
    {
        return Math.Abs(x - y) <= 1e-10;
    }

    public void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
受保护的无效集(ref T storage,T value,[CallerMemberName]string propertyName=null)
{
if(等于(存储、值))
{
回来
}
储存=价值;
OnPropertyChanged(propertyName);
}
受保护的无效集(引用双存储,双值,[CallerMemberName]字符串propertyName=null)
{
if(可忽略的更改(存储、值))
{
回来
}
储存=价值;
OnPropertyChanged(propertyName);
}
私有布尔可忽略更改(双x,双y)
{

return Math.Abs(x-y)提问者发布的答案通常被认为是正确的方法。当你有一个泛型方法,它必须为一个特定类型做一些特殊的事情时,它不再是泛型的

“首先,实际问题从来没有得到回答,第二,关于这个方法要考虑一些问题。

这不起作用,因为它说“不能将T转换为double”。有办法解决这个问题吗

是的,有几种方法可以做到这一点,其中一些方法比其他方法更好

首先,这通常是一种糟糕的类型测试方法

typeof(T) == typeof(double)
您手头有两个Ts,因此您可以这样做:

protected void Set<T>(ref T storage, T value, blah blah blah)
{
    if (Equals(storage, value))
        return;
    double? oldValue = storage as double?;
    double? newValue = value as double?;
    if (oldValue != null && newValue != null && Negligible(oldValue.Value, newValue.Value))
      return;
    ...
将调用双版本,但是

Set<double>(ref someDouble, 1.23)
Set(参考1.23)
仍将调用通用版本。C#更喜欢非通用版本而不是通用版本,但如果您明确要求通用版本,您将得到它

类似地,如果从通用上下文调用您:

class C<T> 
{
  T storage;
  void Frob(Blah blah, T value) {
     blah.Set<T>(ref storage, value);
  }
C类
{
T储存;
无效Frob(废话废话,T值){
blah.Set(参考存储、值);
}
然后
C
不会调用您的特殊版本;同样,这会根据请求调用
Set


所以要小心。

强制转换参数。
可忽略的更改((双)存储,(双)值)
不。这对我不起作用。无论强制转换是隐式的还是显式的,都会出现相同的错误:“error CS0030无法将类型“t”转换为“double”这是非常有用的信息,我将把它标记为答案。但是,我认为我将保留我在下面展示的方法,因为它的编译时间很快,并且我不太可能创建您在最后提到的函数层次结构。我理解您所说的两种方法的差异,但我认为它们编译到same结果-第一个只是第二个的简写。但是,我相信你更清楚。顺便说一下,第一个不是编译。它需要在第一个双精度后加“?”。(我不能添加,因为stackoverflow不允许少于6个字符的修订。
Set<double>(ref someDouble, 1.23)
class C<T> 
{
  T storage;
  void Frob(Blah blah, T value) {
     blah.Set<T>(ref storage, value);
  }