2

So I have a static method that returns a compiled string. The method gets an anonymous object:

var data = new {one = 12.334, two = 235, three = {23, 34, 43}};

And the static method Result should iterate through each value and round the decimals up with:

Math.Round(num, 1);

But I can't seem to find a way to iterate the anonymous object. I want the object to be of type dynamic for easy access when writing to console, but I don't seem to be able to iterate the dynamic object either. I need a way to round up all the values of type double.

public static string Result(object data)
{
    dynamic x = data;

// Iterate through each value and MathRound HERE

    string compiled = $"test1: {x.one};test2: {x.two};test3: {x.three}";

    return compiled;
}

Foreach-method with the dynamic object just throws this error:

Cannot implicitly convert type '<>f__
AnonymousType0<double,int,int[]>' to 'System.Collections.IEnumerable'

And foreach-method with the anonymous object throws this:

foreach statement cannot operate on variables of type 'object' because 'object'
 does not contain a public definition for 'GetEnumerator

I'm a new learner of C#, so I apologize if the terminology is unclear. Do anyone know how to fix this?

Jesper
  • 2,044
  • 3
  • 21
  • 50
  • 1
    `one`, `two`, and `three` are *properties* of the anonymous object, not elements. You can use reflection to iterate through them: data.GetType().GetProperties() ... – Sergey Slepov Mar 28 '17 at 10:07
  • I think this is not a good design, you're abusing the static type system of c# here. Is it really necessary to use an anonymous type? Why can't you declare your own class to store these values? Though it's possible to use reflection here, you won't have any type safety. Will there only be `int` and `int[]` properties or does this method need to take care of other properties that might appear in the anonymous type? – René Vogt Mar 28 '17 at 10:11
  • But how do I apply the Math.round on the values from reflection? – Jesper Mar 28 '17 at 10:12
  • @RenéVogt it's for an assignment, so there won't appear any new properties if that's what you meant. The assignment requires us to use an anonymous object – Jesper Mar 28 '17 at 10:13
  • Besides `three = {23, 34, 43}` will not compile. You could fix it with `three = new [] {23, 34, 43}`. – Sergey Slepov Mar 28 '17 at 10:13
  • @SergeySlepov error shows that type is really `double,int,int[]`, so I guess it's really `new {one = 12.334, two = 235, three = new[] {23, 34, 43}}` – Evk Mar 28 '17 at 10:15
  • You're all forgetting something. Even if you use reflection to iterate the properties of an anonymous object, and even if you work out which ones to apply `Math.Round` to, you cant set the value back as an anonymous object doesnt get setters on its properties. (Error: `System.ArgumentException: Property set method not found.`) eg: http://rextester.com/DNLP73718 – Jamiec Mar 28 '17 at 10:18
  • Process it as a string and replace decimal values by rounded ones. `var s = "{one = 12.334, two = 235, three = {23, 34, 43}}"; var numbers = Regex.Split(s, @"[^0-9\.]+") .Where(c => c != "." && c.Trim() != "") .ToList(); foreach (var decimalString in numbers) { var decimalValue = decimal.Parse(decimalString, CultureInfo.InvariantCulture); var roundedValue = Math.Round(decimalValue, 1); s = s.Replace(decimalString, roundedValue.ToString(CultureInfo.InvariantCulture)); }` – Tomas Chabada Mar 28 '17 at 10:25
  • I found a solution, but the question is marked as duplicate, so can't post the answer. But I basically remade the anonymous object to an ExpandoObject, and with dictionary I cloned the ExpandoObject, edited the values, and then used the clone. – Jesper Mar 28 '17 at 13:19

0 Answers0