简体   繁体   English

C#7.0中的泛型函数和ref返回

[英]Generic functions and ref returns in C# 7.0

Is it possible to use the ref returns feature in C# 7.0 define a generic function that can do both comparison and update of a field in two instances of an Object? 是否可以在C#7.0中使用ref returns功能定义一个泛型函数,它可以在Object的两个实例中同时进行字段的比较和更新? I am imagining something like this: 我想象的是这样的:

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

Example intended usage: 用途示例:

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);

Is there any way to specify a Func type or any kind of generic type restriction that would make this valid by requiring that getter return a reference? 有没有办法指定一个Func类型或任何类型的泛型类型限制,通过要求getter返回引用来使其有效? I tried Func<TClass, ref TField> , but it doesn't appear to be valid syntax. 我尝试了Func<TClass, ref TField> ,但它似乎不是有效的语法。

You won't be able to use Func , because it doesn't return the result by reference. 您将无法使用Func ,因为它不会通过引用返回结果。 You'll need to create a new delegate that uses a ref return: 您需要创建一个使用ref return的新委托:

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

Then changing your function to use that delegate is enough for it to work: 然后更改您的函数以使用该委托就足以使其工作:

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

Note that a property cannot be returned by reference. 请注意,不能通过引用返回属性。 You could return a field by reference, or any other variable , but a property is not a variable. 您可以通过引用或任何其他变量返回字段 ,但属性不是变量。

You need to declare your own delegate type for it. 您需要为它声明自己的委托类型。 For example: 例如:

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);
        }
    }
}

(Note the use of "field" instead of "property" everywhere.) (注意到处使用“field”而不是“property”。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM