gpt4 book ai didi

c# - 将属性作为参数传递

转载 作者:可可西里 更新时间:2023-11-01 09:04:07 24 4
gpt4 key购买 nike

我正在创建一个评价函数计算器,对于外行来说,它会选择一些属性,并根据这些属性与某些理想值(评价函数)的接近程度来计算一个值。然后,这使用户能够找到最符合他们要求的项目。

这是我想使用的代码:

public class MeritFunctionLine
{
public Func<CalculationOutput, double> property { get; set; }
public double value { get; set; }
public ComparisonTypes ComparisonType { get; set; }
}

public class MeritFunction
{
public List<MeritFunctionLine> Lines { get; set; }
public double Calculate(CalculationOutput values)
{
double m = 0;
foreach (var item in Lines)
{
m += Math.Abs(values.property - item.value);
}
return m;
}
}

public class CalculationOutput
{
public double property1 { get; set; }
public double property2 { get; set; }
public double property3 { get; set; }
public double property4 { get; set; }
}

显然这不会编译,因为 values 不包含名为 property 的成员,但这里是对我想做的事情的解释:

  1. 创建一个新的 MeritFunction
  2. 向 MeritFunction.Lines 添加任意数量的 MeritFunctionLines
  3. MeritFunctionLine.property 应该指定在 MeritFunction.Calculate 中比较 CalculationOutput 的什么属性

MeritFunction mf = new MeritFunction();
mf.Lines.Add(new MeritFunctionLine() { property = x => x.Property1, value = 90, comparisonType = ComparisonTypes.GreaterThan });
mf.Lines.Add(new MeritFunctionLine() { property = x => x.Property3, value = 50, comparisonType = ComparisonTypes.Equals });

CalculationOutput c1 = new CalculationOutput() { property1 = 1, property2 = 20, property3 = 150, property4 = 500 };
CalculationOutput c2 = new CalculationOutput() { property1 = 15, property2 = 32, property3 = 15, property4 = 45 };

double value1 = mf.Calculate(c1);
double value2 = mf.Calculate(c2);

我不是在问如何将属性作为参数传递给函数,这是 C# 禁止的。

最佳答案

您几乎已经有了正确的解决方案 - 唯一缺少的部分是如何使用 MeritFunctionLine.property 属性从 CalculationOutput 中获取所需的值。

在您的foreach 循环中,只需将计算行替换为

m += Math.Abs(item.property(values) - item.value);

编辑:

添加泛型

为了解决 Obsidian Phoenix 的评论,您可以通过使 MeritFunctionMeritFunctionLine 通用来将其用于不同的类,因此:

public class MeritFunctionLine<TCalcOutput>
{
public Func<TCalcOutput, double> property { get; set; }
public double value { get; set; }
public ComparisonTypes ComparisonType { get; set; }
}

public class MeritFunction<TCalcOutput>
{
public List<MeritFunctionLine<TCalcOutput>> Lines { get; set; }
public double Calculate(TCalcOutput values)
{
double m = 0;
foreach (var item in Lines)
{
m += Math.Abs(item.property(values) - item.value);
}
return m;
}
}

重写的用法示例是

MeritFunction<CalculationOutput> mf = new MeritFunction<CalculationOutput>();
mf.Lines.Add(new MeritFunctionLine<CalculationOutput>() { property = x => x.Property1, value = 90, comparisonType = ComparisonTypes.GreaterThan });
mf.Lines.Add(new MeritFunctionLine<CalculationOutput>() { property = x => x.Property3, value = 50, comparisonType = ComparisonTypes.Equals });

CalculationOutput c1 = new CalculationOutput() { property1 = 1, property2 = 20, property3 = 150, property4 = 500 };
CalculationOutput c2 = new CalculationOutput() { property1 = 15, property2 = 32, property3 = 15, property4 = 45 };

double value1 = mf.Calculate(c1);
double value2 = mf.Calculate(c2);

一些额外的便利

如果您要添加许多 MeritFunctionLine,上面的语法可能会有点乏味。因此,作为奖励,让我们更改 MeritFunction 以便它可以使用列表初始化语法进行初始化。为此,我们需要使其成为 IEnumerable 并为其提供一个 Add 函数:

public class MeritFunction<TCalcOutput> : IEnumerable<MeritFunctionLine<TCalcOutput>>
{
public List<MeritFunctionLine<TCalcOutput>> Lines { get; set; }

public MeritFunction()
{
Lines = new List<MeritFunctionLine<TCalcOutput>>();
}

public void Add(Func<TCalcOutput, double> property, ComparisonTypes ComparisonType, double value)
{
Lines.Add(new MeritFunctionLine<CalculationOutput>
{
property = property,
value = value,
comparisonType = ComparisonType
});
}

public double Calculate(TCalcOutput values)
{
double m = 0;
foreach (var item in Lines)
{
m += Math.Abs(item.property(values) - item.value);
}
return m;
}

public IEnumerator<MeritFunctionLine<TCalcOutput>> GetEnumerator()
{
return List.GetEnumerator();
}

System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}

请注意,Add 方法以不同的顺序接收参数 - 当您查看用法时就会明白为什么。相当多的额外代码,但现在创建我们的 MeritFunction 会更好一些:

MeritFunction<CalculationOutput> mf = new MeritFunction<CalculationOutput>
{
{ x => x.Property1, ComparisonTypes.GreaterThan, 90 },
{ x => x.Property3, ComparisonTypes.Equals, 50 }
};

注意,所有代码都未经测试。使用风险自负:)

关于c# - 将属性作为参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25264550/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com