Home > Back-end >  Returning IEnumerable with an anonymous type
Returning IEnumerable with an anonymous type

Time:07-11

I have an interface similar to this:

IEnumerable<(string valueA, decimal valueB)> GetData

This interface should not be changed. So I'm trying to implement it. I need to use LINQ, so I have this part of code:

var fetchedData = File.ReadAllLines(filePath)
                    .Skip(1)
                    .Select(a => x.Split(';'))
                    .Select(a => new 
                    {
                        valueB= decimal.Parse(a[0]),
                        valueA= a[1]
                    });
return fetchedData;

The problem is that fetchedData is not of the same type the interface expects. I need to return IEnumerable<(string valueA, decimal valueB)> but fetchedData is another type.

CodePudding user response:

You are confusing Anonymous Types and Value Tuples here.

While your interface returns a tuple, your LINQ query yields an anonymous type. Change your query to:

var fetchedData = File.ReadAllLines(filePath)
    .Skip(1)
    .Select(a => x.Split(';'))
    .Select(a => (a[1], decimal.Parse(a[0])));

CodePudding user response:

There are a few issues with your code:

  1. Your interface expects the result to be a Tuple<string, decimal> which is the actual type behind the notation (string valueA, decimal valueB)

  2. Your code, particularly the following line:

    .Select(a => new 
        {
            valueB= decimal.Parse(a[0]),
            valueA= a[1]
        })
    

    produces an anonymous object with the following fields { decimal valueB; string valueA; }. The problem is that the .NET will declare a class to represent the anonymous type, and that is incompatible with the Tuple type you initially request from the interface.

Here is a fix for your code that should satisfy the interface:

var fetchedData = File.ReadAllLines(filePath)
                .Skip(1)
                .Select(a => x.Split(';'))
                .Select(a => (a[1], decimal.Parse(a[0]) ) );
return fetchedData;

CodePudding user response:

Just return a named tuple in your select, instead of an anonymous object :)

IEnumerable<(string valueA, decimal valueB)> GetData()
    => File.ReadAllLines(filePath)
           .Skip(1)
           .Select(a => a.Split(';')) // here, you used x instead of a
           .Select(a => (valueA: a[1], valueB: decimal.Parse(a[0])));

CodePudding user response:

If the interface insist on tuple (named tuple), let's provide it:

return File            // let's drop fetchedData and just return 
  .ReadLines(filePath) // Let's drop All - premature materialization
  .Skip(1)
  .Select(a => x.Split(';'))
  .Select(a => (a[1], decimal.Parse(a[0]));

All you have to do is to change {..} into (...) and keep the right order (first string than decimal). You may want to put the names, but it's not required:

return File
  .ReadLines(filePath)
  .Skip(1)
  .Select(a => x.Split(';'))
  .Select(a => (valueA : a[1], valueB : decimal.Parse(a[0]));
  • Related