Reputation: 794
I have two properties in an object, ChannelName and ChannelValue. I have an Enum with a list of channel Id's.
I want to be able to use a Linq query to say, "select the channel value where the channel name = one of the items in the Enum."
I have this so far, but I get the error:
Cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'string'
The code is:
var channels = Enum.GetNames(typeof(ModbusChannels)).ToList();
var allChannelValues = "";
foreach (var item in channels)
{
allChannelValues = (from x in data where x.ChannelName.Contains(item) select x.ChannelValue);
}
FYI, where 'data' appears in the appears in the query, this is an object that is fully populated.
The Enum has 500 names in it, but here is a shortened version:
public enum ModbusChannels{
M0,
M1,
M2,
M3,
M4,
M5,
M6,
M7,
M8
}
Is this the right way to do this and how do I achieve the query.
Upvotes: 0
Views: 12197
Reputation: 16606
The reason for that error is because allChannelValues
is of type string
, whereas the from x in data ...
expression you are attempting to assign to allChannelValues
results in an IEnumerable<ChannelValueType>
, where ChannelValueType
is the same type as x.ChannelValue
. As the error states, an IEnumerable<ChannelValueType>
cannot be implicitly converted to string
to store in allChannelValues
.
The other answers provide a more efficient way to do this, but just to "finish the thought" of what you had started to do...
List<string> channels = Enum.GetNames(typeof(ModbusChannels)).ToList();
IEnumerable<ChannelValueType> allChannelValues = Enumerable.Empty<ChannelValueType>();
foreach (string item in channels)
{
IEnumerable<ChannelValueType> channelValues = from x in data
where x.ChannelName.Contains(item)
select x.ChannelValue;
allChannelValues = allChannelValues.Concat(channelValues);
}
string allChannelValuesText = string.Join(", ", allChannelValues);
Declaring allChannelValues
with the appropriate type is all that is needed to eliminate the error.
You were also assigning allChannelValues
on every iteration of the foreach
, so at the completion of the loop allChannelValues
would contain the result of only the last iteration. Instead, we store the query results in channelValues
and then concatenate that to allChannelValues
to save the cumulative results of the loop; allChannelValues
is initialized with an empty enumerable so there is something on which to call .Concat()
on the first iteration.
Finally, we use string.Join()
to build a comma-separated string
of the resulting ChannelValue
values. It is not until this line is executed that the LINQ queries/methods in the foreach
block are actually evaluated, but that does not affect the result.
Upvotes: 1
Reputation: 62213
The way I am reading your question is that you want to see if the string value of the property ChannelName
exists as a name in the enumeration ModbusChannels
.
List<string> channels = Enum.GetNames(typeof(ModbusChannels)).ToList();
var allChannelValues = data
.Where(x => channels.Contains(x.ChannelName))
.Select(x => x.ChannelValue)
.ToList();
This will not work if this string value contains multiple values like a CSV string. In that case it would be more clear if you included sample values.
Upvotes: 1
Reputation: 101681
You can use Contains
to check if enum values contain the channel name:
var channels = Enum.GetNames(typeof(ModbusChannels)).ToList();
var allChannelValues = data.Where(d => channels.Contains(d.ChannelName)).ToList();
Upvotes: 5