I want to convert this statement to build a list of VM images to use in testing into something more elegant using the yield keyword, but the syntax is elluding me.
Desired end goal.
List<VmImages> images;
images[0] - WindowsServer2019
images[1] - WindowsServer2016
images[2] - RhelServer;
images[3] - OpenLogic;
Today the code looks like this:
for (var i = 0; i < LinuxVMs; i )
{
switch (i)
{
case 0:
linuxDistros.Add(ConfigLoader.redHat);
break;
case 1:
linuxDistros.Add(ConfigLoader.openLogic);
break;
case 2:
linuxDistros.Add(ConfigLoader.suse);
break;
case 3:
linuxDistros.Add(ConfigLoader.ubuntu);
break;
}
}
This feels like a good case to use the yield keyword to simplify the logic into something like this, where I call GetLinuxVMs()
for x number of times, where X is the count of LinuxVMs
.
private static IEnumerable<VmDistribution> GetLinuxVmDistros()
{
yield return ConfigLoader.redHat;
yield return ConfigLoader.openLogic;
yield return ConfigLoader.suse;
yield return ConfigLoader.canonical;
}
I'm not sure how to integrate this into my code, this is what I've tried:
for (var i = 0; i < LinuxVMs; i )
{
linuxDistros.Add(GetLinuxVmDistros());
}
Since I get an IEnum back from the GetLinuxVmDistros
method every time, I am puzzled as to how this is supposed to work at all.
CodePudding user response:
From your stated "desired end goal"
List<VmImages> images = new(){
WindowsServer2019,
WindowsServer2016,
RhelServer,
OpenLogic,
}
All the rest of the looping/finagling is just confusing the issue, IMHO
CodePudding user response:
GetLinuxVmDistros()
will return an IEnumerable<VmDistribution>
as per your definition.
It seems you want to add to a collection called linuxDistros
another collection.
If linuxDistros
is a List<VmDistribution>
, simply use the AddRange
method:
linuxDistros.AddRange(GetLinuxVmDistros());
See: https://docs.microsoft.com/fr-fr/dotnet/api/system.collections.generic.list-1.addrange?view=net-6.0
But I fail to see the point of creating an Enumerable just for this.
CodePudding user response:
I'm not certain what you try to achieve since the naming is .. not clear. But with this code below, it works:
class ConfigLoader
{
static public VmDistribution redHat { get; set; } = VmDistribution.a;
static public VmDistribution openLogic { get; set; } = VmDistribution.b;
static public VmDistribution suse { get; set; } = VmDistribution.c;
static public VmDistribution canonical { get; set; } = VmDistribution.d;
}
enum VmDistribution { a, b, c, d }
IEnumerable<VmDistribution> GetLinuxVmDistros()
{
yield return ConfigLoader.redHat;
yield return ConfigLoader.openLogic;
yield return ConfigLoader.suse;
yield return ConfigLoader.canonical;
}
var list = new List<VmDistribution>();
list.AddRange(GetLinuxVmDistros());
Notice that in the end I'm invoking GetLinuxVmDistros()
only once, and the list is filled with method list.AddRange()
.
CodePudding user response:
In your example you should do whatever you need to do with the items with the loop.
for (var i = 0; i < LinuxVMs; i )
{
ProcessItem(LinuxVMs[i]);
}
Having said that, there's isn't much point in yielding on such a small set of results. The main purpose of yield return
is to allow a large collection to be returned 1 item at a time, where the calling code may want to stop iterating over the items at any point. Another usage is where fetching all items at once may be very expensive resource-wise.
For example, you may not want to continue if 1 item couldn't be processed for whatever reason.
for (var i = 0; i < LinuxVMs; i )
{
var result = ProcessItem(LinuxVMs[i]);
if (!result.Success)
{
break;
}
}