【问题标题】:Generic functions and ref returns in C# 7.0C# 7.0 中的泛型函数和 ref 返回
【发布时间】:2018-01-27 08:29:19
【问题描述】:

是否可以使用 C# 7.0 中的 ref 返回功能定义一个通用函数,该函数可以在对象的两个实例中进行字段的比较和更新?我在想象这样的事情:

void UpdateIfChanged<TClass, TField>(TClass c1, TClass c2, Func<TClass, TField> getter)
{
    if (!getter(c1).Equals(getter(c2))
    {
        getter(c1) = getter(c2);
    }
}

预期用途示例:

Thing thing1 = new Thing(field1: 0, field2: "foo");
Thing thing2 = new Thing(field1: -5, field2: "foo");
UpdateIfChanged(thing1, thing2, (Thing t) => ref t.field1);
UpdateIfChanged(thing1, thing2, (Thing t) => ref t.field2);

有没有办法指定一个 Func 类型或任何类型的泛型类型限制,通过要求 getter 返回一个引用来使其有效?我试过Func&lt;TClass, ref TField&gt;,但它似乎不是有效的语法。

【问题讨论】:

    标签: c# generics pass-by-reference c#-7.0


    【解决方案1】:

    您将无法使用Func,因为它不会通过引用返回结果。您需要创建一个使用 ref 返回的新委托:

    public delegate ref TResult RefReturningFunc<TParameter, TResult>(TParameter param);
    

    然后将您的函数更改为使用该委托就足够了:

    public static void UpdateIfChanged<TClass, TField>(TClass c1, TClass c2, RefReturningFunc<TClass, TField> getter)
    {
        if (!getter(c1).Equals(getter(c2)))
        {
            getter(c1) = getter(c2);
        }
    }
    

    请注意,不能通过引用返回属性。您可以通过引用或任何其他变量返回字段,但属性不是变量。

    【讨论】:

      【解决方案2】:

      您需要为它声明自己的委托类型。例如:

      using System;
      
      public class Thing
      {
          public int field1;
          public string field2;    
      }
      
      public delegate ref TOutput FuncRef<TInput, TOutput>(TInput input);
      
      public class Test
      {
          public static void Main()
          {
              Thing thing1 = new Thing { field1 = 0, field2 = "foo" };
              Thing thing2 = new Thing { field1 = -5, field2= "foo" };
              UpdateIfChanged(thing1, thing2, (Thing t) => ref t.field1);
              UpdateIfChanged(thing1, thing2, (Thing t) => ref t.field2);
          }
      
          static void UpdateIfChanged<TInput, TOutput>(TInput c1, TInput c2, FuncRef<TInput, TOutput> getter)
          {
              if (!getter(c1).Equals(getter(c2)))
              {
                  getter(c1) = getter(c2);
              }
          }
      }
      

      (注意在所有地方都使用“字段”而不是“属性”。)

      【讨论】:

        猜你喜欢
        • 2017-08-10
        • 2019-05-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-24
        相关资源
        最近更新 更多