C#: Object Array with Constructor parameter - c#

I have a class Measurement.
I have a constructor inside this class. as:
class Measurement
{
public Measurement(MainWindow mainWindow)
{
....
}
}
How can I create an Array of 8 Objects with the MainWindow Parameter?
Like somewhere in my code:
Measurement[] measurements= new Measurement[8](mainWin);

Do you want an array with a single reference 8 times, or 8 separate Measurement objects?
For the first:
var measurements = Enumerable.Repeat(new Measurement(mainWin), 8).ToArray();
For the second:
var measurements = Enumerable.Range(0, 8)
.Select(_ => new Measurement(mainWin))
.ToArray();
(Or just create an array without initializing the elements, then populate it with a loop, of course. It's a matter of personal preference.)

You can use LINQ:
var measurements = Enumerable.Range(0, 8).Select(i => new Measurement(mainWin)).ToArray();
A second way is to use the array initializer syntax:
var measurements = new[] {
new Measurements(mainWin), new Measurements(mainWin),
new Measurements(mainWin), new Measurements(mainWin),
new Measurements(mainWin), new Measurements(mainWin),
new Measurements(mainWin), new Measurements(mainWin)
};

There is this way (by using Enumerable.Repeat) :
var measurements = Enumerable.Repeat(new Measurement(mainWin), 8).ToArray();
Quote :
Generates a sequence that contains one repeated value.

Measurement[] measurements= new Measurement[8];
for(int i = 0; i < measurements.Length; i++)
{
measurements[i] = new Measurement(mainWin);
}

Related

Using a case statement while creating a list

I have a list which is a bunch of functions as displayed below
var listOfSteps = new List<StepList>
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
//72 steps in total
}
I have to add another function to the list based on a condition.
int result = select something from someTable
var listOfSteps = new List<StepList>
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
if (result = 5) {new display(parameters)}, //This is the additional step to be added
//72 steps in total
}
I am trying to avoid creating 2 different sets for a simple if condition like below
if(result = 5)
{
var listOfSteps = new List<StepList> //list with the new function
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
new display(parameters),
//72 steps in total
}
}
else
{ //list without the new function
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
//72 steps in total
}
Is there a way to implement this condition within the list creation?
Collection initializers are just syntactic sugar. Example:
var ints = new List<int> { 1, 2, 3 };
// is equivalent to
var temp = new List<int>();
temp.Add(1);
temp.Add(2);
temp.Add(3);
var ints = temp;
This means that you can simply add this new item conditionally afterwards:
var listOfSteps = new List<StepList>
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
...
}
if (result == 5) {
listOfSteps.Add(new display(parameters));
}
I think it would be very readable if you can add a new kind of step - "do nothing":
// shouldn't StepList be renamed to "Step"?
class DoNothing: StepList {
...
// implement this so that when the list of steps is processed,
// this will do nothing
}
Then, you can use a simple ternary operator:
var listOfSteps = new List<StepList>
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
result == 5 ?
new display(parameters)
:
new DoNothing(),
}
It would be even more readable if you can make factory methods for all your steps, so that you don't have the word new all the time.
You can also use a switch expression:
var listOfSteps = new List<StepList>
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
result switch {
5 => new display(parameters),
_ => new DoNothing(),
}
}
which would be very useful if you have more complicated decisions to make.
If the number of steps in the list of steps is important, you can always just remove the DoNothing steps from the list with a Where when you check the count.
listOfSteps.Where(step => step is not DoNothing).Count()
I suppose that StepList is a class which causes some operation to be performed when its object is encountered. The problem you are facing is that, depending on external condition, one StepList object should be added or not, and that complicates List initialization, right?
If that is the issue, then you may introduce a special "do nothing" StepList subclass, e.g. called Empty. Your list initialization would then look like this:
var listOfSteps = new List<StepList>
{
new Setup(parameters),
new InitializeClass(parameters),
new calculate(parameters),
(result == 5 ? new display(parameters) : new Empty())
// ... 72 steps in total
}
With this design, your list will always have the same number of items, but the result of their execution would depend on external condition.
I would use a method with IEnumerable as return type and do yield returns where necessary.
eg.
private IEnumerable<StepList> GetSteps()
{
yield return new Setup(parameters);
yield return new InitializeClass(parameters);
yield return new calculate(parameters);
if (result = 5) yield return new display(parameters);
...
}
and than intialize the list like this:
var listOfSteps = GetSteps().ToList();
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/yield

How to elegantly populate a heterogeneous array in c#

I have 3 different classes (1 parent and 2 children), and I have created a heterogeneous array:
Parent[] parentArray = new Parent[9];
I would like to populate this array with 3 Parent objects, 3 child1 objects, and 3 child2 objects, in that order.
I would like to know if there is a more elegant way to do it than just doing this:
parentArray[0] = new Parent();
parentArray[1] = new Parent();
parentArray[2] = new Parent();
parentArray[3] = new Child1();
parentArray[4] = new Child1();
....
parentArray[9] = new Child2();
Thanks!
Like this?
var parentArray = new Parent[]
{
new Parent(),
new Parent(),
new Parent(),
new Child1(),
...
};
Personal i just think you should use the object initializer. However for sheer boredom you can use Linq and a generic factory method.
// Given
public static IEnumerable<T> Factory<T>(int count) where T : Parent, new()
=> Enumerable.Range(0, count).Select(x => new T());
...
// Usage
var array = Factory<Parent>(3)
.Union(Factory<Child1>(3))
.Union(Factory<Child2>(3))
.ToArray();
In this situation, you want to perform a certain number of actions repeatedly. Loops are commonly used to do this. Because you're initializing an array, for loops are a good fit, as they expose an integer that can be used to index the array. In your scenario, you can use three such loops.
Parent[] parentArray = new Parent[9];
for (int i = 0; i < 3; i++)
{
parentArray[i] = new Parent();
}
for (int i = 3; i < 6; i++)
{
parentArray[i] = new Child1();
}
for (int i = 6; i < 9; i++)
{
parentArray[i] = new Child2();
}

List with arrays into seperate arrays

I have a constructor which uses a List parameter. Inside that list I have three items which are 3 integer arrays.
public HistogramLogic(List<Tuple<int[], int[], int[]>> separateRGB)
Now I want to initialize three new integer arrays with the arrays inside that list. But when I try this code, the index of my new arrays stay 0.
for (int i = 0; i < histogramXValues.Length; i++)
{
rArray = separateRGB.Select(obj => obj.Item1[i]).ToArray();
gArray = separateRGB.Select(obj => obj.Item2[i]).ToArray();
bArray = separateRGB.Select(obj => obj.Item3[i]).ToArray();
}
Anyone got any suggestions on how to fix this?
Bear in mind, if you have a list of N tuples, you start with 3 x N arrays. Sounds like you want them combined into 3 arrays, each containing all of the elements throughout the list. Which you can do with SelectMany.
rArray = separateRGB.SelectMany(obj => obj.Item1).ToArray();
gArray = separateRGB.SelectMany(obj => obj.Item2).ToArray();
bArray = separateRGB.SelectMany(obj => obj.Item3).ToArray();
Full example:
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
static public void HistogramLogic(List<Tuple<int[], int[], int[]>> separateRGB)
{
var rArray = separateRGB.SelectMany(obj => obj.Item1).ToArray();
var gArray = separateRGB.SelectMany(obj => obj.Item2).ToArray();
var bArray = separateRGB.SelectMany(obj => obj.Item3).ToArray();
Console.WriteLine("rArray = {{{0}}}", string.Join(",", rArray));
Console.WriteLine("gArray = {{{0}}}", string.Join(",", gArray));
Console.WriteLine("bArray = {{{0}}}", string.Join(",", bArray));
}
public static void Main()
{
var mockData = new List<Tuple<int[], int[], int[]>>
{
Tuple.Create(new[] {11,12,13}, new[] {14,15,16}, new[] {17,18,19}),
Tuple.Create(new[] {21,22,23}, new[] {24,25,26}, new[] {27,28,29}),
Tuple.Create(new[] {31,32,33}, new[] {34,35,36}, new[] {37,38,39})
};
HistogramLogic(mockData);
}
}
Output:
rArray = {11,12,13,21,22,23,31,32,33}
gArray = {14,15,16,24,25,26,34,35,36}
bArray = {17,18,19,27,28,29,37,38,39}
Click here for code on DotNetFiddle
You can just get the item from touple
rArray = separateRGB.Select(obj => obj.Item1);
Like they sad in comments you did reassign local member in each loop.
You could use something like this.
public HistogramLogic(List<Tuple<int[], int[], int[]>> separateRGB)
{
List<int> rList = new List<int>();
List<int> gList = new List<int>();
List<int> bList = new List<int>();
separateRGB.ForEach((Tuple<int[], int[], int[]> tpl) =>
{
rList.AddRange(tpl.Item1);
gList.AddRange(tpl.Item1);
bList.AddRange(tpl.Item1);
});
rArray = rList.ToArray();
gArray = gList.ToArray();
bArray = bList.ToArray();
}
If you wish to not use temp List object you should know final count of elements in tuple, create local array member to desired size. and fill it. List are more suitable for adding and expanding elements. Maybe you could use one Linq Statement but if I understand goal is to get one int[] array per color. If you take
separateRGB.AsQueryable().Select(m => m.Item1).ToArray();
as a result you get int[][] result instead of simple int array;

dynamically upcast arrays of identically typed instances

Given this linqpad code:
interface I {}
public class A : I {}
public class B : A {}
void Main()
{
var i = new List<I>(new I[] { new A(), new B(), new A(), new B() });
i.GroupBy(_ => _.GetType()).Select(_ => _.ToArray()).Dump();
}
What is the most efficient way to convert these items into IEnumerables of the actual derived types?
I have a method with signature DoStuffToArray<T>(IEnumerable<T> items)
I need to call it dynamically once for each of different types in the list i. It's a library method that needs to be called with the derived types, not the interface.
I have managed to get two typed arrays using this method, is there a better way?
var typeGroup = i.GroupBy(_ => _.GetType()).ToArray();
var arrays = typeGroup.Select(_ => Array.CreateInstance(_.Key, _.Count())).ToArray();
for (int ai = 0; ai < typeGroup.Length; ai++)
{
var grouping = typeGroup[ai].ToArray();
int index = 0;
Array.ForEach(grouping, _ => arrays[ai].SetValue(_, index++));
}
arrays.Dump("typed arrays");
You are looking for OfType<T>().
var i = new List<I>(new I[] { new A(), new B(), new A(), new B() });
var ayes = i.OfType<A>();
var bees = i.OfType<B>();
DoStuffToArray(ayes);
DoStuffToArray(bees);
Live example: http://rextester.com/HQWP13863
How about:
List<I> i = new List<I>(new I[] {new A(), new B(), new A(), new B()});
var types = i.Select(item => item.GetType()).Distinct();
foreach (var instances in types.Select(type => i.Where(item =>item.GetType() == type)))
{ DoStuffToArray(instances); }
This is as brief as I can think of ...
You collect the types as a Disctinct list and then iterate to extract. This method uses a lot of reflection, though, so performance will not be optimal.

How can i create array of my class with default constructor?

For example
MYCLASS[] myclass = new MYCLASS[10];
Now myclass array is all null array but i want to have default constructed Array .I know that i can write loops for set default constructed but i am looking for more easy and simple way.
If you don't want to write out the loop you could use Enumerable.Range instead:
MyClass[] a = Enumerable.Range(0, 10)
.Select(x => new MyClass())
.ToArray();
Note: it is considerably slower than the method you mentioned using a loop, written here for clarity:
MyClass[] a = new MyClass[10];
for (int i = 0; i < a.Length; ++i)
{
a[i] = new MyClass();
}
var a = Enumerable.Repeat(new MYCLASS(), 10).ToArray();
There isn't an easier way. If you just don't like loops, you could use
MyClass[] array = new[] { new MyClass(), new MyClass(), new MyClass(), new MyClass() };
which would give you an array with 4 elements of type MyClass, constructed with the default constructor.
Otherwise, you just have the option to use a loop.
If you don't want to write that loop every time you want to construct your array, you could create a helper-method, for example as an extension method:
static class Extension
{
public static void ConstructArray<T>(this T[] objArray) where T : new()
{
for (int i = 0; i < objArray.Length; i++)
objArray[i] = new T();
}
}
And then use it like this:
MyClass[] array = new MyClass[10];
array.ConstructArray();
There isn't really a better way. You could do something like:
public static T[] CreateArray<T>(int len) where T : class, new() {
T[] arr = new T[len];
for(int i = 0 ; i <arr.Length ; i++) { arr[i] = new T(); }
return arr;
}
then at least you only need:
Foo[] data = CreateArray<Foo>(150);
This approach should at least avoid any reallocations, and can use the JIT array/length optimisation. The : class is to avoid use with value-types, as with value-types already initialize in this way; just new MyValueType[200] would be better.
You can use LINQ.
var a = (from x in Enumerable.Range(10) select new MyClass()).ToArray();
If we want to do all job in only one line code so this is best
MYCLASS[] myclass = (new MYCLASS[10]).Select(x => new MYCLASS()).ToArray();

Categories