C# func<> 应用于左边的对象

C# func<> applied to the object on left

我想弄清楚是否有办法使用应用于左侧对象的 func(或类似方法)。 例如:

member1.MyFunction()

这是一个简化的用法上下文。我们得到了 ClassA,它包含一个 ClassB 的列表和一个总结 classB 的元素的方法。而classB拥有两个double类型的属性memberX和memberY。 func 用于选择我们要求和的 ClassB 的哪个成员。

我写的那一行有错误

theSum += TheList[i].TheFunction();

错误是:

CS1061 C# does not contain a definition for and no extension method accepting a first argument of type could be found (are you missing a using directive or an assembly reference?)

有人知道解决方法吗?我的研究无法将我引导到适用于通用函数左侧的任何内容。

public class ClassA
{
    public List<ClassB> TheList;
    public ClassA()
    {
        ClassB m1 = new ClassB(1, 2);
        ClassB m2 = new ClassB(1, 2);
        ClassB m3 = new ClassB(1, 2);
        TheList= new List<ClassB>() { m1, m2, m3 };
    }
    private double CalculateSum(Func<double> TheFunction)
    {
        double theSum = 0;
        for (int i = 0; i < TheList.Count(); i++)
        {
            theSum += TheList[i].TheFunction();
            // I'd like to use the previous line instead of having to write
            // a function for both of the following.
            // theSum += TheList[i].GetMember1();
            // theSum += TheList[i].GetMember2();
        }
        return theSum;
    }
}
public class ClassB
{
    private double memberX;
    private double memberY;
    public ClassB(double x, double y)
    {
        memberX = x;
        memberY = y;
    }
       
    public double GetMember1() { return memberX; }
    public double GetMember2() { return memberY; }
}

嗯,不是那种语法,但你可以使用:

theSum += aFunction(aList[i]);

我想你可以为此写一个扩展方法,但上面的方法更惯用。

事实上,使用 LINQ 开始会更惯用 - 您的 calculateSum 方法已经作为 Sum 存在于 LINQ 中,因此您可以调用:

double sum = aList.Sum(x => x.getMember1());

当然,更惯用的是,您将使用属性而不是方法:

double sum = aList.Sum(x => Member1);

同样对于习语,您要确保您执行的任何方法都遵循 .NET 命名约定,以大写字母开头。我强烈建议您立即开始遵循命名约定(即使是一次性演示代码)。

您可以尝试这样的操作:

private double calculateSum(Func<ClassB, double> aFunction)
{
    double theSum = 0;
    for (int i = 0; i < aList.Count(); i++)
    {
        theSum += aFunction(aList[i]);
    }

    return theSum;
}

更新

如果你真的想把函数应用到它左边的对象上,那么你可以定义一个扩展方法。

public static class ClassBExtensions
{
    public static double Sum(this ClassB arg, Func<ClassB, double> func)
    {
        return func(arg);
    }
}

然后这样称呼它

Func<ClassB, double> func = null; // define your func here
for (int i = 0; i < aList.Count(); i++)
    {
        theSum += aList[i].Sum(func);
     }
 return theSum;

如果我没理解错的话,您需要一种方法 "on" ClassB returns 其中一个值。 (ClassB 是否应该有这样的方法 - 它可能只是计算的一部分,因此实际上属于 ClassA - 是一个不同的问题。)

如果您可以更改 ClassB,只需在此处添加:

public class ClassB
{
    private double memberX;
    private double memberY;
    public ClassB(double x, double y)
    {
        memberX = x;
        memberY = y;
    }

    public double GetMember1() { return memberX; }
    public double GetMember2() { return memberY; }

    public double AFunction() 
    {
        bool condition = ...
        return condition ? memberX : memberY;
    }
}

我在这里使用三元运算符 ?: 来节省 if/else 上的一些空间。

现在,如果您可以 更改 ClassBextension methods(如 CS1061 错误消息中所暗示)可能会帮助您:

public static class ClassBExtensions
{
    public double AFunction(this ClassB b)
    {
        bool condition = ...
        return condition ? b.GetMember1() : b.GetMember2();
    }
}

您现在可以简单地在类型 ClassB 的任何实例上调用 .AFunction(),就好像该方法最初是在那里声明的一样。请注意,扩展方法只能访问可公开访问的字段。

您可能还想查看 properties,它可以将您的 ClassB 定义减少为:

public class ClassB
{
    public ClassB(double x, double y)
    {
        MemberX = x;
        MemberY = y;
    }

    public double Member1 { get; }
    public double Member2 { get; }

    /*
    public double AFunction() 
    {
        bool condition = ...
        return condition ? Member1 : Member2;
    }
    */
}