SamuraiJack
SamuraiJack

Reputation: 5549

Unexpected result while generating string with Aggregate() in linq

FIDDLE

Utility Function:

  public static string GetProperties<T>(string alias="")
    {
       if (alias.Length>0)
       {
          return typeof(T).GetProperties().Select(x => x.Name).Aggregate((x, y) => 
            alias + " = " + alias + "." + x + "," + Environment.NewLine + alias + " = " + alias + "." + y + ",");
       }
       else
       {
           return typeof(T).GetProperties().Select(x => x.Name).Aggregate((x, y) => x + Environment.NewLine + y);
       }
    }

Code:

    public class ContainerInLog
    {

        public int ContainerInLogID { get; set; }
        public int ContainerInID { get; set; }
        public int CargoID { get; set; }      
        public int LoadStatus { get; set; }    

    }

    public static void Main()
    {
         string list = GetProperties<ContainerInLog>("y");
        Console.WriteLine(list);
    }

Result:

y = y.y = y.y = y.ContainerInLogID,
y = y.ContainerInID,,
y = y.CargoID,,
y = y.LoadStatus,

Expected Result:

ContainerInLogID = y.ContainerInLogID,
ContainerInID = y.ContainerInID,
CargoID = y.CargoID,
LoadStatus = y.LoadStatus,

Upvotes: 0

Views: 74

Answers (2)

w5l
w5l

Reputation: 5766

@DavidG has the nicer solution here, but whats going wrong with your aggregation is the following:

.Aggregate((x, y) => 
            alias + " = " + alias + "." + x + "," + Environment.NewLine + alias + " = " + alias + "." + y + ",");

The Aggregate selector function (your (x,y)) takes the following form:

Func<TAccumulate,TResult> resultSelector

That means in your case, x is the accumulated aggregate result already, eg "ContainerInLogID = y.ContainerInLogID".

But to make the next aggregate, you transform x again: alias + " = " + alias + "." + x, making "y = y.y = y.ContainerInLogID". And so on for each following property, each one adding another prefix of "y = y.".

Upvotes: 1

DavidG
DavidG

Reputation: 119086

If you are really stuck on returning the entire concatenated string instead of returning an enumerable of them, I wouldn't use Aggregate here, just use string.Join. Also, you can simplify the statement by crafting the string inside the Select. For example:

return string.Join(
    Environment.NewLine,
    typeof(T)
        .GetProperties()
        .Select(x => $"{x.Name} = {alias}.{x.Name},"));

Bonus: If you change the separator to $",{Environment.NewLine}" you can remove the inline comma and you won't get the final comma on the end of your string (example fiddle).

Upvotes: 5

Related Questions