Хранение функций в свойствах класса C #? - PullRequest
0 голосов
/ 31 января 2019

Мне нужно создать список, содержащий объекты устройства.Эти объекты имеют свойства, которые описывают их Имя, Единицу и Преобразование.Преобразование немного особенное, поскольку это должна быть функция.Например: если у меня был датчик температуры, измеряющий в градусах Фаренгейта, метод его преобразования должен рассчитать и вернуть значение в градусах Цельсия.И если у меня есть датчик влажности, его преобразование будет другим и т.д. Ниже приведен пример того, как я пытался сделать это, но он не работает.Я получаю сообщения о том, что при конвертации разрешено только назначение.

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 голосов
/ 31 января 2019

Вы хотите 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); 
    ...
  }
}

Или вы можете даже получить массив преобразованных значений (double[]) с помощью Linq :

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();
0 голосов
/ 31 января 2019

Попробуйте этот код: используйте 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"
      }
   };
}
...