C# - How to populate a custom class array containing integer primitives? - c#

I have a simple C# program that contains a Coord class that stores an integer x and y value. I want to treat the Coord class like an array, as shown in the Main method. I have seen similar approaches to this in C++ and I would like to know the C# equivalent.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lab6 {
class Coord {
public int x;
public int y;
}
class Program {
static void Main(string[] args) {
Coord[] c = {{1, 2}, {5, 8}, {3, 40}, {6, 3}, {15, 12}, {1, 5}};
}
}
}

You have to put instances of Coord class in the Coord []
Coord[] c = new Coord[4];
c[0] = new Coord(1,3);
....
Or a better way
Coord[] c = {new Coord(1,2),new Coord(1,6)};
Dont forget to add the constructor and initialize the fields
public Coord(int x,int y){
this.x = x;
this.y = y;
}

In C# 9.0 (.NET 5), a record type would be best for this situation:
// Declaration
record Coord(int X, int Y);
// Implicit "new".
Coord[] c = new Coord[] { new(1, 2), new(5, 8) };
new() (with the type omitted) was also introduced in C# 9.0. This might get you closer to what you wanted originally.
Record types
This wasn't part of your question, but if you want immutable data, records are the way to go in new versions of C#. Positional records, like in the example above, are immutable: I don't how you plan on using your Coord type, but if you don't change the x or y value after instantiation, an immutable type is probably what you want.
If you are unable to use .NET 5, you might consider using a struct instead, for similar reasons.
From the record type docs (emphasis added):
You use class definitions to create object-oriented hierarchies that focus on the responsibilities and behavior of objects. You create struct types for data structures that store data and are small enough to copy efficiently. You create records when you want value-based equality and comparison, don't want to copy values, and want to use reference variables.

If you are using C#9, you can instead A. use a record class and B. rely on target-typed new with the generated constructor:
public record Coord(int X, int Y);
public void YourMethod() {
Coord[] c = { new(1,2), new(2,3) };
}
This also has the benefit that you can deconstruct the points into variables, which feels natural for a Coord type:
Coord[] c = { new(1,2), new(2,3) };
var (x, y) = c[0];
// you get withers too!
var cNew = c[0] with { X = 5 };
Without records you can still use target-typing so long as you have an appropriate constructor.
class Coord {
public int X { get; } // you should use properties, not exposed fields
public int Y { get; }
public Coord(int x, int y) => (X, Y) = (x, y);
}
// later
Coord[] c = { new(1,2), new(2,3) };
Or the best of all worlds (depending on your viewpoint), a mutable record with withers, deconstruction and simple target typing:
record Coord(int X, int Y) {
public int X { get; set; } = X;
public int Y { get; set; } = Y;
}

The best you can do with the code as-is looks like this:
Coord[] c = {
new Coord() {x=1,y=2},
new Coord() {x=5,y=8},
//...
};
We can improve slightly on this by adding a constructor:
class Coord
{
public int x;
public int y;
public Coord(int X, int Y) {x = X; Y=y;}
}
Which gets us to here:
Coord[] c = {
new Coord(1,2),
new Coord(5,8),
//...
};
But once you're open to changing the code for the type we can do all kinds of things:
class Coord
{
public int x;
public int y;
public Coord(int X, int Y) {x = X; Y=y;}
public static IEnumerable<Coord> SeqFrom2DIntArray(int[,] input)
{
for(int i=0;i<input.GetUpperBound(0);i++) Console.WriteLine(b[x,0]);
{
yield return new Coord(input[i,0], input[i,1]}; // can throw an exception if the input is bad
}
}
}
And now you can create your Coord objects like this:
//must be a separate line/variable/object for the initializer
int[,] b = {{1, 2}, {5, 8}, {3, 40}, {6, 3}, {15, 12}, {1, 5}};
var c = Coord.SeqFrom2DIntArray(c);
Or if you really need an array (hint: very often IEnumerable by itself is enough and will perform much better):
//must be a separate line/variable/object for the initializer
int[,] b = {{1, 2}, {5, 8}, {3, 40}, {6, 3}, {15, 12}, {1, 5}};
var c = Coord.SeqFrom2DIntArray(c).ToArray();
Which is very close to the original request and doesn't even need C# 9's new toys.

Related

Is it possible to pass List elements as arguments for methods in C#? [duplicate]

Is there any implementation in C# like JavaScript's spread syntax?
var arr = new []{
"1",
"2"//...
};
Console.WriteLine(...arr);
There isn't a spread option. And there are reasons.
Method Parameters aren't an array in C# unless you use the params keyword
Method Parameters that use the param keyword would have to either:
Share the same type
Have a castable shared type such as double for numerics
Be of type object[] (as object is the root type of everything)
However, having said that, you can get similar functionality with various language features.
Answering your example:
C#
var arr = new []{
"1",
"2"//...
};
Console.WriteLine(string.Join(", ", arr));
The link you provide has this example:
Javascript Spread
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers));
// expected output: 6
console.log(sum.apply(null, numbers));
Params
In C#, with same type
public int Sum(params int[] values)
{
return values.Sum(); // Using linq here shows part of why this doesn't make sense.
}
var numbers = new int[] {1,2,3};
Console.WriteLine(Sum(numbers));
In C#, with different numeric types, using double
public int Sum(params double[] values)
{
return values.Sum(); // Using linq here shows part of why this doesn't make sense.
}
var numbers = new double[] {1.5, 2.0, 3.0}; // Double usually doesn't have precision issues with small whole numbers
Console.WriteLine(Sum(numbers));
Reflection
In C#, with different numeric types, using object and reflection, this is probably the closest to what you are asking for.
using System;
using System.Reflection;
namespace ReflectionExample
{
class Program
{
static void Main(string[] args)
{
var paramSet = new object[] { 1, 2.0, 3L };
var mi = typeof(Program).GetMethod("Sum", BindingFlags.Public | BindingFlags.Static);
Console.WriteLine(mi.Invoke(null, paramSet));
}
public static int Sum(int x, double y, long z)
{
return x + (int)y + (int)z;
}
}
}
One trick to get a behavior similar to this (without reflection) is to accept params SomeObject[][] and to also define an implicit operator from SomeObject to SomeObject[]. Now you can pass a mixture of arrays of SomeObject and individual SomeObject elements.
public class Item
{
public string Text { get; }
public Item (string text)
{
this.Text = text;
}
public static implicit operator Item[] (Item one) => new[] { one };
}
public class Print
{
// Accept a params of arrays of items (but also single items because of implicit cast)
public static void WriteLine(params Item[][] items)
{
Console.WriteLine(string.Join(", ", items.SelectMany(x => x)));
}
}
public class Test
{
public void Main()
{
var array = new[] { new Item("a1"), new Item("a2"), new Item("a3") };
Print.WriteLine(new Item("one"), /* ... */ array, new Item("two"));
}
}
there is no direct pre-built library in C# to handle what is built into Spread
In order to get that functionality in C#, you need to Reflect the object and get the methods, properties, or fields by their access modifiers.
You'd do something like:
var tempMethods = typeof(myClass).GetMethods();
var tempFields = typeof(myClass).GetFields();
var tempProperties = typeof(myClass).GetProperties();
then iterate through and throw them into your dynamic object:
using System;
using System.Collections.Generic;
using System.Dynamic;
namespace myApp
{
public class myClass
{
public string myProp { get; set; }
public string myField;
public string myFunction()
{
return "";
}
}
class Program
{
static void Main(string[] args)
{
var fields = typeof(myClass).GetFields();
dynamic EO = new ExpandoObject();
foreach (int i = 0; i < fields.Length; i++)
{
AddProperty(EO, "Language", "lang" + i);
Console.Write(EO.Language);
}
}
public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
{
// ExpandoObject supports IDictionary so we can extend it like this
var expandoDict = expando as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
expandoDict[propertyName] = propertyValue;
else
expandoDict.Add(propertyName, propertyValue);
}
}
}
https://www.oreilly.com/learning/building-c-objects-dynamically
you can also do the following
var a = new List<int>(new int[]{1,2,3}){5};
Console.WriteLine(a.Count);
will print 4
if you want to achieve initialization of lists or arrays with both an accompanying enumerable and parameters

C# js-like spread (or triple dot) operator [duplicate]

Is there any implementation in C# like JavaScript's spread syntax?
var arr = new []{
"1",
"2"//...
};
Console.WriteLine(...arr);
There isn't a spread option. And there are reasons.
Method Parameters aren't an array in C# unless you use the params keyword
Method Parameters that use the param keyword would have to either:
Share the same type
Have a castable shared type such as double for numerics
Be of type object[] (as object is the root type of everything)
However, having said that, you can get similar functionality with various language features.
Answering your example:
C#
var arr = new []{
"1",
"2"//...
};
Console.WriteLine(string.Join(", ", arr));
The link you provide has this example:
Javascript Spread
function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(...numbers));
// expected output: 6
console.log(sum.apply(null, numbers));
Params
In C#, with same type
public int Sum(params int[] values)
{
return values.Sum(); // Using linq here shows part of why this doesn't make sense.
}
var numbers = new int[] {1,2,3};
Console.WriteLine(Sum(numbers));
In C#, with different numeric types, using double
public int Sum(params double[] values)
{
return values.Sum(); // Using linq here shows part of why this doesn't make sense.
}
var numbers = new double[] {1.5, 2.0, 3.0}; // Double usually doesn't have precision issues with small whole numbers
Console.WriteLine(Sum(numbers));
Reflection
In C#, with different numeric types, using object and reflection, this is probably the closest to what you are asking for.
using System;
using System.Reflection;
namespace ReflectionExample
{
class Program
{
static void Main(string[] args)
{
var paramSet = new object[] { 1, 2.0, 3L };
var mi = typeof(Program).GetMethod("Sum", BindingFlags.Public | BindingFlags.Static);
Console.WriteLine(mi.Invoke(null, paramSet));
}
public static int Sum(int x, double y, long z)
{
return x + (int)y + (int)z;
}
}
}
One trick to get a behavior similar to this (without reflection) is to accept params SomeObject[][] and to also define an implicit operator from SomeObject to SomeObject[]. Now you can pass a mixture of arrays of SomeObject and individual SomeObject elements.
public class Item
{
public string Text { get; }
public Item (string text)
{
this.Text = text;
}
public static implicit operator Item[] (Item one) => new[] { one };
}
public class Print
{
// Accept a params of arrays of items (but also single items because of implicit cast)
public static void WriteLine(params Item[][] items)
{
Console.WriteLine(string.Join(", ", items.SelectMany(x => x)));
}
}
public class Test
{
public void Main()
{
var array = new[] { new Item("a1"), new Item("a2"), new Item("a3") };
Print.WriteLine(new Item("one"), /* ... */ array, new Item("two"));
}
}
there is no direct pre-built library in C# to handle what is built into Spread
In order to get that functionality in C#, you need to Reflect the object and get the methods, properties, or fields by their access modifiers.
You'd do something like:
var tempMethods = typeof(myClass).GetMethods();
var tempFields = typeof(myClass).GetFields();
var tempProperties = typeof(myClass).GetProperties();
then iterate through and throw them into your dynamic object:
using System;
using System.Collections.Generic;
using System.Dynamic;
namespace myApp
{
public class myClass
{
public string myProp { get; set; }
public string myField;
public string myFunction()
{
return "";
}
}
class Program
{
static void Main(string[] args)
{
var fields = typeof(myClass).GetFields();
dynamic EO = new ExpandoObject();
foreach (int i = 0; i < fields.Length; i++)
{
AddProperty(EO, "Language", "lang" + i);
Console.Write(EO.Language);
}
}
public static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
{
// ExpandoObject supports IDictionary so we can extend it like this
var expandoDict = expando as IDictionary<string, object>;
if (expandoDict.ContainsKey(propertyName))
expandoDict[propertyName] = propertyValue;
else
expandoDict.Add(propertyName, propertyValue);
}
}
}
https://www.oreilly.com/learning/building-c-objects-dynamically
you can also do the following
var a = new List<int>(new int[]{1,2,3}){5};
Console.WriteLine(a.Count);
will print 4
if you want to achieve initialization of lists or arrays with both an accompanying enumerable and parameters

How to use a string to invoke a function via and interface

So here's a simple example put up where I can add and subtract based on a string input. Then instead of calculating on the spot I wanted to create functions so that I can create an interface. The idea: Use the to refer to anything. I want to put and objects in there, with a uniform way of calling the objects (e.g. they all have an interface that exposes a Compute() method) So here are my two pieces of code that I can't get to mesh to complete this.
public class Calculator
{
private Dictionary<string, Func<float,float,float>> _map = new Dictionary<string, Func<float,float,float>>
{
{ "add", (a,b) => a+b },
{ "subtract", (a,b) => a-b },
{ "multiply", (a,b) => a*b },
{ "divide", (a,b) => a/b },
};
public float Compute(float[] numbers, string opCode)
{
var operation = _map[opCode];
float accumulator = numbers[0];
foreach (var n in numbers.Skip(1))
{
accumulator = operation(accumulator, n);
}
return accumulator;
}
}
public class Program
{
public static void Main()
{
var c = new Calculator();
Console.WriteLine(c.Compute( new float[] { 2,2 }, "add"));
Console.WriteLine(c.Compute( new float[] { 3,3 }, "multiply"));
Console.WriteLine(c.Compute( new float[] {-2,2 }, "subtract"));
Console.WriteLine(c.Compute( new float[] { 9,3 }, "divide"));
}
}
that demonstrates what outputs I'm looking for. Now creating the interface how do I use it in a similar fashion to the above framework?
public interface ICalculate
{
int Calculate(int x, int y);
}
public class Add : ICalculate
{
#region ICalculate Members
public int Calculate(int x, int y)
{
return x + y;
}
#endregion
}
public class Subtract : ICalculate
{
#region ICalculate Members
public int Calculate(int x, int y)
{
return x - y;
}
#endregion
}

Sort 2D array in C#

I was trying to compare a 2D array in C# using IComparer but not able to compile the code from my point of view in sort method ab is assumed to be a jagad array instead of a normal array .Does any one know how to solve that
int[,] ab = new int[3, 4]
{
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 2, 3, 4, 5 }
};
Array.Sort<int[]>(ab, new ComparerTwoDArray());
foreach (var i in ab)
{
Console.WriteLine(i);
}
class ComparerTwoDArray : IComparer<int[]>
{
int ix;
public int Compare(int[] x, int[] y)
{
return x[0].CompareTo(y[0]);
}
}
You are not using the proper method: https://msdn.microsoft.com/en-us/library/system.array.sort%28v=vs.110%29.aspx
Array.Sort Method: Sorts the elements in a one-dimensional array.
You could use List<List<int>> and then use its Sort LINQ extension, like:
list.Sort((x,y) => x[0].CompareTo(y[0]));
Unfortunately a multi-dimensional array is a quite static beast. You can easily access single elements within it by providing the n-dimensional coordinates (eg. array[2,8,4] in a 3d array), but you can't access any whole areas (like rows, columns, rectangles, etc.).
If you really have the need to do such a kind of re-sorting you shouldn't save your data within a multi-dimensional array. Instead put it into a jagged array or a list of lists or even a IReadOnlyDictionary<int, IReadOnlyDictionary<int, IReadOnlyDictionary<int, int>>> for a 4 dimensions sparse matrix. In that case you could quite easily write a comparer for each dimension as you like.
In your case you just need a something like List<IReadOnlyList<int>> and a IComparer<IReadOnlyList<T>> which could possibly be implemented like this:
public class ListComparer<T> : IComparer<IReadOnlyList<T>>
{
public static readonly IComparer<IReadOnlyList<T>> Default = new ListComparer<T>();
private readonly bool _checkCount;
private readonly int _numberOfElementsToCompare;
private readonly IComparer<T> _elementComparer;
public ListComparer()
: this(true, 1, Comparer<T>.Default)
{
}
public ListComparer(
bool checkCount,
int numberOfElementsToCompare,
IComparer<T> elementComparer)
{
_checkCount = checkCount;
_numberOfElementsToCompare = numberOfElementsToCompare;
_elementComparer = elementComparer
?? throw new ArgumentNullException(nameof(elementComparer));
}
public int Compare(IReadOnlyList<T> x, IReadOnlyList<T> y)
{
if (ReferenceEquals(x, y))
return 0;
if (ReferenceEquals(x, null))
return -1;
if (ReferenceEquals(y, null))
return 1;
if (_checkCount)
{
var diff = x.Count.CompareTo(y.Count);
if (diff != 0)
return diff;
}
return x.Take(_numberOfElementsToCompare)
.Zip(y, (i, j) => _elementComparer.Compare(i, j))
.SkipWhile(value => value == 0)
.FirstOrDefault();
}
}
And would be used:
var matrix = new List<IReadOnlyList<int>>
{
{ new List<int> { 1, 2, 3, 4 } },
{ new List<int> { 5, 6, 7, 8 } },
{ new List<int> { 2, 3, 4, 5 } }
};
matrix.Sort(ListComparer<int>.Default);
foreach (var item in matrix)
{
Console.WriteLine(String.Join(", ", item));
}

Convert C++ array of struct w/o tons of new calls?

C++
typedef struct someStruct {
int val1, val2;
double val3;
} someStruct;
someStruct a [1000] = { {0, 0, 0.0}, {1, 1, 1.0}, ... };
The only way to initialize such a table in C# I know of is to write something like
class SomeStruct
{
int val1, val2;
double val3;
public SomeStruct (int val1, int val2, double val3)
{
this.val1 = val1;
this.val2 = val2;
this.val3 = val3;
}
}
SomeStruct[] a = new SomeStruct [1000]
{
new SomeStruct (0, 0, 0.0),
new SomeStruct (1, 1, 1.0),
...
};
Is there a way to have a be a (reference to) an array of values of type class SomeClass instead to pointers to those?
Edit:
The point is that I want to avoid having to call new for each struct in the array. So what I want is an array containg 1000 structs and not 1000 pointers to (1000) structs. The reason I am asking is that the way C# handles this appears insanely inefficent to me, involving a lot of memory and memory management overhead (over e.g. C++).
I had tried something like
struct SomeStruct {
int a, b;
double c;
}
SomeStruct[] a = new SomeStruct [1000] { {0,0,0.0}, {1,1,1.0}, ... };
But that wasn't possible. So though I know that structs are value types, I concluded that this is only true when passing them as parameters to function, and I had to use new, like this (using structs here):
struct SomeStruct {
int a, b;
double c;
SomeStruct (int a, int b, double c) {
this.a = a; this.b = b; this.c = c;
}
}
SomeStruct[] a = new SomeStruct [1000] {
new SomeStruct {0,0,0.0},
new SomeStruct {1,1,1.0},
...
};
You can use the struct keyword in C#. C# structs are value types- an array of structs is contiguously stored structs, identical to a C++ standard array.
It's ugly, but this will work (if you change the type to struct instead of class)
SomeStruct[] a = new SomeStruct [1000];
a[0].val1 = 0;
a[0].val2 = 1;
a[0].val3 = 2.0;
...
a[999].val1 = 0;
a[999].val2 = 1;
a[999].val3 = 2.0;
Edit:
If this is a global field, declare a as static readonly.
You can do this by creating a new collection for SomeStruct (derived from IEnumerable<>) Each item you use in the initialization syntax gets converted to a call to .Add(...), so provided your collection class has a method called Add (doesn't need to inherit from any other interface for this), with matching arguments, you can use the same C++ syntax.
eg.
public class SomeStructCollection : IEnumerable<SomeStruct> {
private readonly SomeStruct[] someStructs = new SomeStruct[1000];
private int currentIndex;
public void Add(int val1, int val2, double val3) {
someStructs[currentIndex++] = new SomeStruct(val1, val2, val3);
}
public SomeStruct this[int index] {
get { return someStructs[index];
}
//Implement IEnumerable<> interface.
}
Calling code can then wrap values in some blocks
SomeStructCollection coll = new SomeStructCollection {
{0, 0, 0.0}, {1, 1, 1.0}, { ... },
};

Categories