C# params keyword accepting multiple arrays - c#

Consider this method
public static void NumberList(params int[] numbers)
{
foreach (int list in numbers)
{
Console.WriteLine(list);
}
}
I can call this method and supply seperated single integers or just one array with several integers. Within the method scope they will be placed into an array called numbers (right?) where I can continue to manipulate them.
// Works fine
var arr = new int[] { 1, 2, 3};
NumberList(arr);
But if I want to call the method and supply it arrays instead, I get an error. How do you enable arrays for params?
// Results in error
var arr = new int[] { 1, 2, 3};
var arr2 = new int[] { 4, 5, 6 };
NumberList(arr, arr2);

The type you're requiring is an int[]. So you either need to pass a single int[], or pass in individual int parameters and let the compiler allocate the array for you. But what your method signature doesn't allow is multiple arrays.
If you want to pass multiple arrays, you can require your method to accept any form that allows multiple arrays to be passed:
void Main()
{
var arr = new[] { 1, 2, 3 };
NumberList(arr, arr);
}
public static void NumberList(params int[][] numbers)
{
foreach (var number in numbers.SelectMany(x => x))
{
Console.WriteLine(number);
}
}

public void Test()
{
int[] arr1 = {1};
int[] arr2 = {2};
int[] arr3 = {3};
Params(arr1);
Params(arr1, arr2);
Params(arr1, arr2, arr3);
}
public void Params(params int[][] arrs)
{
}

Your method is only set to accept a single array. You could use a List if you wanted to send more than one at a time.
private void myMethod(List<int[]> arrays){
arrays[0];
arrays[1];//etc
}

You cant by langauge means.
However there is a way to work arround this by overlading the method something like this:
public static void NumberList(params int[][] arrays)
{
foreach(var array in arrays)
NumberList(array);
}
See here

Related

A nicer way to add a new value to string array?

I have the following code:
private void AddMissingValue(ref string[] someArray) {
string mightbemissing="Another Value";
if (!someArray.Contains(mightbemissing)) {
var lst=someArray.ToList();
lst.Add(mightbemissing);
someArray=lst.ToArray();
}
}
While this works (Add an item to an array if missing), I wonder if this can be done in a smarter way? I don't like converting the array twice and writing so many lines for such a simple task.
Is there a better way? Maybe using LinQ?
General idea is right - array is a fixed-sized collection and you cannot add an item to it without recreating an array.
Your method can be written in a slightly more elegant way using LINQ .Concat method without creating a List:
private void AddMissingValue(ref string[] someArray)
{
string mightbemissing = "Another Value";
if (!someArray.Contains(mightbemissing))
{
someArray = someArray.Concat(new[] { mightbemissing }).ToArray();
}
}
This implementation takes N * 2 operations which is better than your N * 3, but it is still enumerating it multiple times and is quadratic for adding N items to your array.
If you are going to perform this operation too often, then changing your code to use dynamic-size collections (f.i., List) would be a more effective way.
Even if you decide to continue using arrays, it probably (imo) will look better if you return modified array instead of using ref:
private string[] AddMissingValue(string[] someArray)
{
string mightbemissing = "Another Value";
return someArray.Contains(mightbemissing)
? someArray
: someArray.Concat(new[] { mightbemissing }).ToArray();
}
// Example usage:
string[] yourInputArray = ...;
yourInputArray = AddMissingValue(yourInputArray);
LINQ-style and the most performant
Another implementation which comes to my mind and is the best (O(N)) in terms of performance (not against dynamic-size collections, but against previous solutions) and is LINQ-styled:
public static class CollectionExtensions
{
public static IEnumerable<T> AddIfNotExists<T>(this IEnumerable<T> enumerable, T value)
{
bool itemExists = false;
foreach (var item in enumerable)
{
if (!itemExists && value.Equals(item))
itemExists = true;
yield return item;
}
if (!itemExists)
yield return value;
}
}
// Example usage:
string[] arr = ...;
arr = arr.AddIfNotExists("Another Value").ToArray();
This implementation with yield is used to prevent multiple enumeration.
If you need to add multiple items, then it can even be rewritten this way, and it seems to still be linear:
public static IEnumerable<T> AddIfNotExists<T>(this IEnumerable<T> enumerable, params T[] value)
{
HashSet<T> notExistentItems = new HashSet<T>(value);
foreach (var item in enumerable)
{
if (notExistentItems.Contains(item))
notExistentItems.Remove(item);
yield return item;
}
foreach (var notExistentItem in notExistentItems)
yield return notExistentItem;
}
// Usage example:
int[] arr = new[] { 1, 2, 3 };
arr = arr.AddIfNotExists(2, 3, 4, 5).ToArray(); // 1, 2, 3, 4, 5
You have to resize the array, see
https://msdn.microsoft.com/en-us/library/bb348051(v=vs.110).aspx
for details. Implementation:
// static: it seems that you don't want "this" in the method
private static void AddMissingValue(ref string[] someArray) {
string mightbemissing = "Another Value";
if (!someArray.Contains(mightbemissing)) {
Array.Resize(ref someArray, someArray.Length + 1);
someArray[someArray.Length - 1] = mightbemissing;
}
}
In you current implementation, you copy all the items twice which can be unwanted if the array is large
...
var lst=someArray.ToList(); // first: all data copied from array to list
lst.Add(mightbemissing);
someArray=lst.ToArray(); // second: all data copied from list to array
A better design, however, is to switch from fixed size array string[] to, say, List<string>:
List<string> someList = ...
if (!someList.Contains(mightbemissing))
someList.Add(mightbemissing); // <- just Add
if all the values should be not null and unique you can do further improvement:
HashSet<string> someHash = ...
someHash.Add(mightbemissing);

Elegant initialization of an array of class instances in C# [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
Let's say I have a class like this:
public class Fraction
{
int numerator;
int denominator;
public Fraction(int n, int d)
{
// set the member variables
}
// And then a bunch of other methods
}
I want to initialize an array of them in a nice way, and this post is a big list of approaches that are error prone or syntactically cumbersome.
Of course an array constructor would be nice, but there's no such thing:
public Fraction[](params int[] numbers)
So I'm forced to use a method like
public static Fraction[] CreateArray(params int[] numbers)
{
// Make an array and pull pairs of numbers for constructor calls
}
which is relatively clunky, but I don't see a way around it.
Both forms are error prone because a user could mistakenly pass an odd number of parameters, maybe because s/he skipped a value, which would leave the function scratching its head wondering what the user actually wanted. It could throw an exception, but then the user would need to try/catch. I'd rather not impose that on the user if possible. So let's enforce pairs.
public static Fraction[] CreateArray(params int[2][] pairs)
But you can't call this CreateArray in a nice way, like
Fraction.CreateArray({0,1}, {1,2}, {1,3}, {1,7}, {1,42});
You can't even do
public static Fraction[] CreateArray(int[2][] pairs)
// Then later...
int[2][] = {{0,1}, {1,2}, {1,3}, {1,7}, {1,42}};
Fraction.CreateArray(numDenArray);
Note that this would work just fine in C++ (I'm pretty sure).
You're forced to do one of the following instead, which is abhorrent. The syntax is terrible and it seems really awkward to use a jagged array when all the elements have the same length.
int[2][] fracArray = {new int[2]{0,1}, /*etc*/);
Fraction.CreateArray(fracArray);
// OR
Fraction.CreateArray(new int[2]{0,1}, /*etc*/);
Similarly, Python-style tuples are illegal and the C# version is icky:
Fraction.CreateArray(new Tuple<int,int>(0,1), /*etc*/);
The use of a pure 2D array might take the following form, but it's illegal, and I'm sure there's no legal way to express it:
public static Fraction[] CreateArray(int[2,] twoByXArray)
// Then later...
Fraction[] fracArray =
Fraction.CreateArray(new int[2,4]{{0,1}, {1,2}, {1,3}, {1,6}});
This doesn't enforce pairs:
public static Fraction[] CreateArray(int[,] twoByXArray)
OK, how about
public static Fraction[] CreateArray(int[] numerators, int[] denominators)
But then the two arrays might have different lengths. C++ allows
public static Fraction[] CreateArray<int N>(int[N] numerators, int[N] denominators)
but, well, this isn't C++, is it?
This sort of thing is illegal:
public static implicit operator Fraction[](params int[2][] pairs)
and unworkable anyway, again because of the abhorrent syntax:
Fraction[] fracArray = new Fraction[](new int[2]{0,1}, /*etc*/ );
This might be nice:
public static implicit operator Fraction(string s)
{
// Parse the string into numerator and denominator with
// delimiter '/'
}
Then you can do
string[] fracStrings = new string[] {"0/1", /*etc*/};
Fraction[] fracArray = new Fraction[fracStrings.Length];
int index = 0;
foreach (string fracString in fracStrings) {
fracArray[index] = fracStrings[index];
}
I don't like this approach for five reasons. One, the implicit cast unavoidably instantiates a new object, but we already have a perfectly good one, namely the one we're trying to initialize. Two, it can be confusing to read. Three, it forces you to do explicitly what I wanted to encapsulate in the first place. Four, it leaves room for bad formatting. Five, it involves one-time parsing of string literals, which is more like a practical joke than good programming style.
The following also requires wasteful instantiation:
var fracArray = Array.ConvertAll(numDenArray, item => (Fraction)item);
The following use of a property has the same problem unless you use those terrible jagged arrays:
public int[2] pair {
set {
numerator = value[0];
denominator = value[1];
}
}
// Then later...
var fracStrings = new int[2,4] {{0,1}, /*etc*/};
var fracArray = new Fraction[fracStrings.Length];
int index = 0;
foreach (int[2,] fracString in fracStrings) {
fracArray[index].pair = fracStrings[index];
}
This variation doesn't enforce pairs:
foreach (int[,] fracString in fracStrings) {
fracArray[index].pair = fracStrings[index];
}
Again, this approach is big anyway.
These are all of the ideas I know how to derive. Is there a good solution?
I can't think of an elegant, and at the same time memory efficient solution for array.
But there is an elegant solution for list (and similar) utilizing the C# 6 collection initializer feature:
public static class Extensions
{
public static void Add(this ICollection<Fraction> target, int numerator, int denominator)
{
target.Add(new Fraction(numerator, denominator));
}
}
With that extension method in place, you can easily initialize a Fraction list for instance:
var list = new List<Fraction> { { 0, 1 }, { 1, 2 }, { 1, 3 }, { 1, 7 }, { 1, 42 } };
And of course, although not memory efficient, you can use it to initialize Fraction array either:
var array = new List<Fraction> { { 0, 1 }, { 1, 2 }, { 1, 3 }, { 1, 7 }, { 1, 42 } }.ToArray();
or even making it more concise by declaring a list derived class with implicit array conversion operator:
public class FractionList : List<Fraction>
{
public static implicit operator Fraction[](FractionList x) => x?.ToArray();
}
and then use
Fraction[] array = new FractionList { { 0, 1 }, { 1, 2 }, { 1, 3 }, { 1, 7 }, { 1, 42 } };
You could create a fraction array builder with a fluent interface. It would lead to something like
public class FractionArrayBuilder
{
private readonly List<Fraction> _fractions = new List<Fraction>();
public FractionArrayBuilder Add(int n, int d)
{
_fractions.Add(new Fraction(n, d));
return this;
}
public Fraction[] Build()
{
return _fractions.ToArray();
}
}
which can be called using
var fractionArray = new FractionArrayBuilder()
.Add(1,2)
.Add(3,4)
.Add(3,1)
.Build();
which is an easy to understand statement.
I have made a fiddle to demonstrate.
The most succinct way I can think of for your particular example involves writing an implicit operator for the Fraction class:
public sealed class Fraction
{
public Fraction(int n, int d)
{
Numerator = n;
Deniminator = d;
}
public int Numerator { get; }
public int Deniminator { get; }
public static implicit operator Fraction(int[] data)
{
return new Fraction(data[0], data[1]);
}
}
Then you can initialise it like this:
var fractions = new Fraction[]
{
new [] {1, 2},
new [] {3, 4},
new [] {5, 6}
};
Unfortunately you still need the new [] on each line, so I don't think this gains very much over the normal array initialisation syntax:
var fractions = new []
{
new Fraction(1, 2),
new Fraction(3, 4),
new Fraction(5, 6)
};
I suppose you could write a "local" Func<> with a short name to simplify the initialisation somewhat:
Func<int, int, Fraction> f = (x, y) => new Fraction(x, y);
var fractions = new []
{
f(1, 2),
f(3, 4),
f(5, 6)
};
The drawback is that you'd need to add that extra line (initialising a Func<>) wherever you wanted to initialise the array - or have a private static method in the class instead - but then that method would be in scope throughout the class, which isn't ideal if it has a single-letter name.
However, the advantage of this approach is that it is very flexible.
I toyed with the idea of calling the inline function _, but I'm really not sure about that...
Func<int, int, Fraction> _ = (x, y) => new Fraction(x, y);
var fractions = new []
{
_(1, 2),
_(3, 4),
_(5, 6)
};

What is C# equivalent of TSQL's "IN" operator? What are the ways to check if X exists in X,Y,Z in c#?

What are the ways to check if X exists in X,Y,Z in c#?
For eg:
X=5;
I want to check if X's value matches any of the comma separated values..
if(x in (2,5,12,14)
new int[] { 2,5,12,14}.Contains(x);
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
list.Contains(5);
You may use .Contains method. e.g. listItems.Contains(x)
There is no in operator in C#, but you can implement an extension method to make the code more readable.
public static class Ext
{
public static bool In<T>(this T val, params T[] values) where T : struct
{
return values.Contains(val);
}
}
//usage: var exists = num.In(numbers);
Linq.Contains() what you searching for
// Create List with three elements.
var list = new List<string>();
list.Add("cat");
list.Add("dog");
list.Add("moth");
// Search for this element.
if (list.Contains("dog"))
{
Console.WriteLine("dog was found");
}
There are two methods Linq.Contains() method and an extension Linq.Contains<int>
var list = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// Use extension method.
var stp = new Stopwatch();
stp.Start();
bool a = list.Contains<int>(7);
stp.Stop();
Console.WriteLine("Time in extenstion method {0}", stp.Elapsed);
stp.Restart();
// Use instance method.
bool b = list.Contains(7);
stp.Stop();
Console.WriteLine("Time in normal method {0}", stp.Elapsed);
Performance benchmark : The version specific to List i.e, list.Contains(7); , found on the List type definition, is faster. I tested the same List with the two Contains methods.

Why can't new int[] and new[] be omitted for arguments and elements of an array?

static void Main(string[] args)
{
int[][] data =// new int[][] has been omitted here!
{
new int[] {1,2,3},// new int[] cannot be omitted
new int[] {1,2,3,4}// new int[] cannot be omitted
};
Foo(new[] { 1, 2, 3 });// new[] cannot be omitted
}
static void Foo(int[] data) {/* implementation omitted */}
Why can't new int[] and new[] be omitted for arguments and elements of an array?
You can do this:
int[,] data2 =// new int[][] has been omitted here!
{
{1,2,3}, // new int[] would make no sense
{1,2,3}
};
and that's partially your answer. The initializer you want to use already has another meaning.
Suppose you wrote var data3 = { {1,2}, {2, 3} };. Would data3 be an int[,] or an int[][] ?
Array initializer syntax ({ ... }) can only be used to initialize a field or variable.
There is no default initialization for the elements of a jagged array. Because it's elements are also arrays. That's why you have to use new [] when you declare them.
That's why you can't do that;
int[][] data =
{
{1,2,3},
{1,2,3,4}
};
But you can do that in single of multi-dimensional array because theirs elements are variable.
int[,] data =
{
{1,2,3},
{1,2,3}
};
or
int[] data =
{
1,
2,
3
};
From 12.6 Array initializers
The context in which an array initializer is used determines the type
of the array being initialized. In an array creation expression, the
array type immediately precedes the initializer. In a field or
variable declaration, the array type is the type of the field or
variable being declared.
For parameter part, there is no new usage for any type of arrays. Read 10.5.1 Method parameters.
For most comman usage is params. For example;
static void Foo(params int[] data) {/* implementation omitted */}
static void Main(string[] args)
{
int[] array = {1, 2, 3};
Foo(array);
Foo(1, 2, 3, 4);
}
Actually, Foo(1, 2, 3, 4); automatically creates a four-element int[] with the given values. It equals to call Foo(new int[] {1,2,3,4})
A side-note, really: you can omit the types in the inner array declarations:
int[][] data =
{
new [] {1,2,3},
new [] {1,2,3,4}
};
static void Foo(int[] data) {/* implementation omitted */}
new
static void Foo(params int[] data)
To provide the invoke of array of elements as method parameters , you need to use the key word params
It seems that feature is not implemented as specification doesn't say anything about that.
The context in which an array initializer is used determines the type
of the array being initialized. In an array creation expression, the
array type immediately precedes the initializer. In a field or
variable declaration, the array type is the type of the field or
variable being declared. When an array initializer is used in a field
or variable declaration, such as:
int[] a = {0, 2, 4, 6, 8};
Taken from 12.6 Array initializers

C#: Create and pass variable straight in the method call

I would like to know how to declare new variable straight in the parameter brackets and pass it on like this:
MethodA(new int[]) //but how to fill the array if declared here? E.g. how to declare and set string?
MethodA(int[] Array)
...
and what if need to declare an object (class with constructor parameter)? Still possible within parameter list?
MethodA(new int[] { 1, 2, 3 }); // Gives an int array pre-populated with 1,2,3
or
MethodA(new int[3]); // Gives an int array with 3 positions
or
MethodA(new int[] {}); // Gives an empty int array
You can do the same with strings, objects, etc:
MethodB(new string[] { "Do", "Ray", "Me" });
MethodC(new object[] { object1, object2, object3 });
If you want to pass a string through to a method, this is how you do it:
MethodD("Some string");
or
string myString = "My string";
MethodD(myString);
UPDATE:
If you want to pass a class through to a method, you can do one of the following:
MethodE(new MyClass("Constructor Parameter"));
or
MyClass myClass = new MyClass("Constructor Parameter");
MethodE(myClass );
You can try this:
MethodA(new int[] { 1, 2, 3, 4, 5 });
This way you achieve the functionality you asked for.
There seems to be no way to declare a variable inside parameter list; however you can use some usual tricks like calling a method which creates and initializes the variable:
int[] prepareArray(int n)
{
int[] arr = new int[n];
for (int i = 0; i < n; i++)
arr[i] = i;
return arr;
}
...
MethodA(prepareArray(5));
...
With the strings, why not just use string literal:
MethodB("string value");
?
Either new int[0] or new int {} will work for you. You can also pass in values, as in new int {1, 2, 3}. Works for lists and other collections too.
In your case you would want to declare MethodB(string[] strArray) and call it as MethodB(new string[] {"str1", "str2", "str3" })
P.S.
I would recomment that you start with a C# tutorial, for example this one.
Do you simply mean:
MethodA("StringValue"); ??
As a side note: if you add the params keyword, you can simply specify multiple parameters and they will be wrapped into an array automatically:
void PrintNumbers(params int[] nums)
{
foreach (int num in nums) Console.WriteLine(num.ToString());
}
Which can then be called as:
PrintNumbers(1, 2, 3, 4); // Automatically creates an array.
PrintNumbers(new int[] { 1, 2, 3, 4 });
PrintNumbers(new int[4]);

Categories

Resources