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

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();

Related

Initialize a number of instances inside a list [duplicate]

I have a method which takes in N, the number of objects I want to create, and I need to return a list of N objects.
Currently I can do this with a simple loop:
private static IEnumerable<MyObj> Create(int count, string foo)
{
var myList = new List<MyObj>();
for (var i = 0; i < count; i++)
{
myList .Add(new MyObj
{
bar = foo
});
}
return myList;
}
And I'm wondering if there is another way, maybe with LINQ to create this list.
I've tried:
private static IEnumerable<MyObj> CreatePaxPriceTypes(int count, string foo)
{
var myList = new List<MyObj>(count);
return myList.Select(x => x = new MyObj
{
bar = foo
});
}
But this does seem to populate my list.
I tried changing the select to a foreach but its the same deal.
I realized that the list has the capacity of count and LINQ is not finding any elements to iterate.
myList.ForEach(x => x = new MyObj
{
bar = foo
});
Is there a correct LINQ operator to use to get this to work? Or should I just stick with the loop?
You can use the Range to create a sequence:
return Enumerable.Range(0, count).Select(x => new MyObj { bar = foo });
If you want to create a List, you'd have to ToList it.
Mind you though, it's (arguably) a non-obvious solution, so don't throw out the iterative way of creating the list just yet.
You could create generic helper methods, like so:
// Func<int, T>: The int parameter will be the index of each element being created.
public static IEnumerable<T> CreateSequence<T>(Func<int, T> elementCreator, int count)
{
if (elementCreator == null)
throw new ArgumentNullException("elementCreator");
for (int i = 0; i < count; ++i)
yield return (elementCreator(i));
}
public static IEnumerable<T> CreateSequence<T>(Func<T> elementCreator, int count)
{
if (elementCreator == null)
throw new ArgumentNullException("elementCreator");
for (int i = 0; i < count; ++i)
yield return (elementCreator());
}
Then you could use them like this:
int count = 100;
var strList = CreateSequence(index => index.ToString(), count).ToList();
string foo = "foo";
var myList = CreateSequence(() => new MyObj{ Bar = foo }, count).ToList();
You can Use Enumerable.Repeat
IEnumerable<MyObject> listOfMyObjetcs = Enumerable.Repeat(CreateMyObject, numberOfObjects);
For more info read https://msdn.microsoft.com/en-us/library/bb348899(v=vs.110).aspx

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.

Easy initialization of string arrays within a class

If a class contains just string array variables, is there an easy way to initialize them all without having to type the same code over and over?
For example, if I have something like
[Serializable]
public class ReadDiagnosticEntirePointValuesResponse
{
public string[] pointidentifier;
public string[] presentvalue;
public string[] priorityarray;
public string[] alarmstate;
public string[] outofservice;
public string[] correctvalue;
public string[] affect;
public string[] covenable;
public string[] covincrement;
public string[] covtarget;
public string[] covlifetime;
public string[] historyenable;
public string[] historyincrement;
public string[] elapsedactivetime;
public string[] feedbackvalue;
public string[] rawvalue;
...//A lot more
}
and I want to assign values to to them, I want to avoid doing:
ReadDiagnosticEntirePointValuesResponse response = new ReadDiagnosticEntirePointValuesResponse();
response.affect = new string[count];
response.alarmstate = new string[count];
response.correctvalue = new string[count];
response.covenable = new string[count];
response.covincrement = new string[count];
response.covlifetime = new string[count];
response.covtarget = new string[count];
response.elapsedactivetime = new string[count];
response.feedbackvalue = new string[count];
response.historyenable = new string[count];
response.historyincrement = new string[count];
response.outofservice = new string[count];
response.pointidentifier = new string[count];
response.presentvalue = new string[count];
response.priorityarray = new string[count];
response.rawvalue = new string[count];
...
Sure, I could write those initialization in constructor but that still doesn't save me from having to manually initialize them all.
What's a good way to avoid this?
That is a pretty horrible way to manage your data, however, something like the following would work....
foreach(var field in GetType().GetFields()) {
if(!field.IsStatic) field.SetValue(this, new string[count]);
}
However! I strongly suggest you rethink this design. A better mechanism would be:
class DiagnosticPoint // TODO: rename as appropriate
{ // TODO: check these all need to be strings
public string Affect {get;set;}
public string AlarmState {get;set;}
...
public string RawValue {get;set;}
}
and have an array of that as a field:
public class ReadDiagnosticEntirePointValuesResponse
{
DiagnosticPoint[] points;
...
then simply init the array:
points = new DiagnosticPoint[count];
and init each:
for(int i = 0 ; i < count ; i++) points[i] = new DiagnosticPoint();
and access via:
var alarm = points[index].AlarmState;
(etc)
You can use Reflection to do this:
public ReadDiagnosticEntirePointValuesResponse()
{
GetType().GetFields(BindingFlags.Instance | BindingFlags.Public)
.ToList()
.ForEach(field => field.SetValue(this, new string[count]));
}
At least once you have to initialize them manually. if C'tor doesn't suit you, initialize in a new method.
You might want to look at reflection for that... Reading the class' proprties in a loop
This sounds like an awful class definition. Perhaps using an enum might be better.
If you could start with this:
public enum ReadDiagnostic
{
pointidentifier,
presentvalue,
priorityarray,
alarmstate,
outofservice,
correctvalue,
affect,
covenable,
covincrement,
covtarget,
covlifetime,
historyenable,
historyincrement,
elapsedactivetime,
feedbackvalue,
rawvalue,
}
You could then create a Dictionary<ReadDiagnostic, string[]> to hold your values that you were storing in your class.
You could even use LINQ to create your dictionary in one line of code:
var readDiagnosticEntirePointValues =
typeof(ReadDiagnostic)
.GetEnumValues()
.Cast<ReadDiagnostic>()
.ToDictionary(x => x, x => new string[count]);
This approach is still strongly-typed, but much easier to maintain than your current approach.
You could use the following:
response.affect = response.alarmstate = response... = new string[count];
However, using this will still have you initialize them manually. It's just a shortcut.
As others may already have suggested, using Collection Classes will make it a lot easier. I would recommend a Dictionary. Here is how you could implement it:
enum Foo { Affect, AlarmState, CorrectValue, ... }
public void InitializeArrays(int count)
{
Dictionary<Foo, string[]> response = new Dictionary<Foo, string[]>();
// easy initialization of string arrays
foreach (Foo foo in Enum.GetValues(typeof(Foo)))
{
response.Add(foo, new string[count]);
}
// use this to access the string arrays
response[Foo.Affect][0] = "test";
if (response[Foo.CorrectValue].Length > 0) { ... }
}
Alternatively, you could also achieve the same by using a Multidimensional Array.
// initialize it like this
string[,] response = new string[Enum.GetValues(typeof(Foo)).Length, count];
// access it like this
response[(int)Foo.Affect, 0] = "test";
You can use the array list to avoid of declaring the size.

Categories