0

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.

3 Answers 3

5

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();
Sign up to request clarification or add additional context in comments.

1 Comment

You could also use a HashSet<> for channels (e.g. var channels = new HashSet<ModbusChannels>((ModbusChannels[]) Enum.GetNames(typeof(ModbusChannels)));) to avoid the linear search of a List/array.
1

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.

3 Comments

That is correct. There about 2,000 channel Id's in the Enum. I want to select the ChannelValue from the 'data' object, if the ChannelName exists in the Enum.
@TheOrangeGoblin - well that should do it then. I am not sure what the ChannelValue type is, I had it as the same enum type but that was an assumption.
I tried it, but I keep getting conversion errors. I used this as offered by Selman below: var channels = Enum.GetNames(typeof(Channels)).ToList(); var allChannelValues = data.Where(d => channels.Contains(d.ChannelName)).Select(d => d.ChannelValue).ToList();
1

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.

1 Comment

I really appreciate the time you have taken to explain it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.