I am trying to iterate over a list that I grab by doing solutionInformation.GetType().GetProperties().GetValue(). But even though the type is an IList, I get an exception when I try to iterate over the value.
namespace NS
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class Accelerator
{
public string AccName { get; set; }
}
public class DeviceInfo
{
public int Ram { get; set; }
public List<Accelerator> Accelerator { get; set; }
}
public class SolutionPods
{
public DeviceInfo DeviceInfo { get; set; }
}
public class Solution
{
public List<SolutionPods> SolutionPods { get; set; }
}
public class HelloWorld
{
public static void Main(string[] args)
{
var acc1 = new Accelerator { AccName = "accelerator Name" };
List<Accelerator> accList1 = new List<Accelerator>();
accList1.Add(acc1);
var devInfo1 = new DeviceInfo { Ram = 64, Accelerator = accList1 };
var solComponet = new SolutionPods { DeviceInfo = devInfo1 };
List<SolutionPods> SCList = new List<SolutionPods>();
SCList.Add(solComponet);
var solution = new Solution { SolutionPods = SCList };
foreach (var solutionComponet in solution.SolutionPods)
{
var solutionInformation = solutionComponet.DeviceInfo;
foreach (var solutionProperty in solutionInformation.GetType().GetProperties())
{
var solutionValue = solutionProperty.GetValue(solutionInformation);
if (solutionValue is IList)
{
Console.WriteLine("IList found");
// System.Collections.Generic.List`1[NS.Accelerator]
Console.WriteLine(solutionValue);
/*
/tmp/AFBHdRy49g.cs(64,43): error CS1579: foreach statement cannot operate on variables of type 'object' because 'object' does not contain a public instance definition for 'GetEnumerator'
*/
foreach (var s in solutionValue)
{
Console.WriteLine(s);
}
}
}
}
Console.WriteLine("Setup Complete");
}
}
}
Am I not actually grabbing a list? Or do I need to convert the object into a different form so that it has an GetEnumerator property?
CodePudding user response:
In C#, once a variable is declared, it keeps the type it's declared as. In your case, the var solutionValue
uses the inferred type of object
because that's what Property.GetValue()
returns.
The compiler does not implement type narrowing when it encounters a conditional like this:
if (solutionValue is IList)
However, you can use pattern matching to declare a new variable with the correct type:
if (solutionValue is IList solutions)
{
...
foreach (var s in solutions)
CodePudding user response:
The compiler does a static type check that the value provided is (statically) an IEnumerable
. An object
is not. A (IList)solutionValue
would be.
if (solutionValue is IList list) // joining a type test and a cast
{
foreach (var s in list) // here list is an IList
{
Console.WriteLine(s);
}
}