Reputation: 125
I need to create a list containing Device objects. These objects have properties that describe their Name, Unit and Conversion. Conversion is a bit special as this is supposed to be a function. For example: If I had a temperature sensor measuing in farenheit, its conversion method should calculate and return the value in celsius. And if I have a moisture sensor, its conversion will be different etc. Below is an example of how I have tried doing this but it doesn't work. I get errors saying that only assignment is allowed on Conversion.
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"
}
};
Upvotes: 2
Views: 6415
Reputation: 186678
You want Func<double, double>
instead of Action
; given double
(e.g. 4.5
Volt) return double
.
x => x / 1000
On the contrary, Action
takes no arguments and returns nothing: () => {...}
Code:
// 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"),
};
Possible usage:
// 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);
...
}
}
Or you can even have an array of converted values (double[]
) with a help of 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();
Upvotes: 0
Reputation: 1627
Try this code:
use Func
instead of Action
.
Func can return value where as Action Can't.
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"
}
};
}
Upvotes: 1