在C#类属性中存储函数?

时间:2019-01-31 10:40:30

标签: c# function delegates

我需要创建一个包含设备对象的列表。这些对象具有描述其名称,单位和转换的属性。转换有点特殊,因为它应该是一个函数。例如:如果我有一个以华氏度进行测量的温度传感器,则其转换方法应以摄氏度为单位计算并返回该值。而且,如果我有湿度传感器,其转换会有所不同,等等。以下是我尝试执行此操作的示例,但它不起作用。我收到错误消息,指出仅允许在“转换”上进行分配。

private class Device
{
    public string Name { get; set; }
    public Action Conversion { get; set; }
    public string Unit { get; set; }
}

public static object ParseDecentLab(byte[] bytes)
{

    List<Device> deviceList = new List<Device>()
    {
        new Device()
        {
            Name = "battery-voltage",
            Conversion = (x) => x / 1000,
            Unit = "V"
        },
        new Device()
        {
            Name = "air-temperature",
            Conversion = (x) => (175 * x / 65535) - 45,
            Unit = "°C"
        }
    };

2 个答案:

答案 0 :(得分:0)

尝试以下代码: 使用Func而不是Action

  

Func可以在操作无法执行的地方返回值。

private class Device
{
   public string Name { get; set; }
   public Func<double,double> Conversion { get; set; }
   public string Unit { get; set; }
}

public static object ParseDecentLab(byte[] bytes)
{        
   List<Device> deviceList = new List<Device>()
   {
      new Device()
      {
         Name = "battery-voltage",
         Conversion = (x) => x / 1000,
         Unit = "V"
      },
      new Device()
      {
         Name = "air-temperature",
         Conversion = (x) => (175 * x / 65535) - 45,
         Unit = "°C"
      }
   };
}

答案 1 :(得分:0)

您想要Func<double, double>而不是Action;给定double(例如4.5伏)返回double

x => x / 1000

相反,Action不接受任何参数,不返回任何值:() => {...}

代码:

// Let's implement immutable class (assigned once, never change)
// in order to prevent occasional errors like device.Name = ... 
private class Device {
  public string Name { get; }
  public Func<double, double> Conversion { get; }
  public string Unit { get; }

  // Let's validate the input (at least, for null)
  public Device(string name, Func<double, double> conversion, string unit) {
    if (null == name)
      throw new ArgumentNullException(nameof(name));
    else if (null == conversion)
      throw new ArgumentNullException(nameof(conversion));
    else if (null == unit)
      throw new ArgumentNullException(nameof(unit));

    Name = name;
    Conversion = conversion;
    Unit = unit;
  }
}

...

List<Device> deviceList = new List<Device>() {
  new Device("battery-voltage", x => x / 1000, "V"),
  new Device("air-temperature", x => (175 * x / 65535) - 45, "°C"),
};

可能的用法:

// What device should we use if we want °C unit?
Device temperature = deviceList
  .FirstOrDefault(item => item.Unit == "°C");

byte[] dataToConvert = new byte[] {123, 45, 79};

// Device found
if (temperature != null) {
  // Converting: for each value in dataToConvert we obtain corresponding t value
  foreach (var value in dataToConvert) {
    double t = temperature.Conversion(value); 
    ...
  }
}

或者借助 Linq ,您甚至可以拥有一组转换后的值(double[]):

byte[] dataToConvert = new byte[] {123, 45, 79};

// Let's throw exception if device has not been found
Device temperature = deviceList
  .First(item => item.Unit == "°C");

double[] results = dataToConvert
  .Select(v => temperature.Convert(v))
  .ToArray();