Is there some pattern/syntaxis/library for C# to accomplish something like the delegate helper method that exists on Ruby on Rails (https://apidock.com/rails/Module/delegate)?
The problem is that if you google for delegates for C# you only find information about the delegate concept of C# that is slightly different from the concept in rails.
And continuing with the trip, is there an equivalent too for Javascript/Typescript?
There is no equivalent in c#, you need to implement it (create a facade method) manually in each case.
An example from the link:
class Foo
CONSTANT_ARRAY = [0,1,2,3]
##class_array = [4,5,6,7]
def initialize
#instance_array = [8,9,10,11]
end
delegate :sum, to: :CONSTANT_ARRAY
delegate :min, to: :##class_array
delegate :max, to: :#instance_array
end
Foo.new.sum # => 6
Foo.new.min # => 4
Foo.new.max # => 11
Could be translated to c# as:
public class Foo
{
public static readonly IReadOnlyList<int> CONSTANT_ARRAY = new[] {0, 1, 2, 3};
public static int[] class_array = {4, 5, 6, 7};
public int[] instance_array = {8, 9, 10, 11};
public int sum() => CONSTANT_ARRAY.Sum();
public int min() => class_array.Min();
public int max() => this.instance_array.Max();
}
...
new Foo().sum(); // => 6
new Foo().min(); // => 4
new Foo().max(); // => 11
Related
I saw NRE when using array initializer in object initializer and there was a update and https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#extension-add-methods-in-collection-initializers but still I cannot understand.
var arr = new int[] { 1, 2, 3 } generate IL code using stelem.
But int[] arr = { 1, 2, 3 } generate IL code using RuntimeHelpers.InitializeArray. I think it is using Array.Add extension method which was talk in that answer.
But in object initializer, all array initializer generate second code.
An example,
new A() {
arr = new int[] { 1, 2, 3 }
}
Array arr is created using RuntimeHelpers.InitializingArray too. Then, doesn't it mean there isn't any problem in next code?
new A() {
arr = { 1, 2, 3 } // Compiler error!
}
Not like old version of c# compiler, it makes compiler error saying system.array does not contain a definition for Add. What's happening?
EDIT
I thought just syntax without new [] makes differences but actually more than three elements makes different IL code.
The second syntax ( { arr = {... } }) is syntax sugar for sequence of value.arr.Add(.) - presumably value.arr is not initialized in your constructor and hence NRE.
Assuming A is:
class A {
public int[] arr {get;set}
}
then
var x = new A() {
arr = { 1, 2, 3 } // Compiler error!
};
is the same as
var x = new A(); // note x.arr is default null here
x.arr.Add(1); // NRE is arr is list, can't compile for int[]
x.arr.Add(2);
x.arr.Add(3);
Fix: use list, there is no reasonable way to add elements to an array.
If using some other type that does not have .Add - implement extension method that is visible to that code.
Why version with new works:
var x = new A() {
arr = new int[] { 1, 2, 3 }
};
is equivalent* of
var x = new A();
x.arr = new int[] { 1, 2, 3 };
Note that in array initializer you can use both syntaxes to the same effect, but not in array field's initializers (All possible C# array initialization syntaxes)
int[] x = { 10, 20, 30 }; // valid, same as int[] x = new int[]{ 10, 20, 30 };
while new A { arr = { 10, 20, 30} } is not the same as new A { arr = new int[3]{ 10, 20, 30} }
*It is really a bit more complicated to satisfy rules when change must be observable - see Eric Lippert's comment below
In an expression context these are legal array values:
new int[3] { 10, 20, 30 }
new int[] { 10, 20, 30 }
new[] { 10, 20, 30 }
In a local or member variable initializer context, this is a legal array initializer:
int[] x = { 10, 20, 30 };
And this is a legal collection initializer:
List<int> x = new List<int> { 10, 20, 30 };
And, if X<T> is IEnumerable<T> and has a method Add(T, T, T), this is legal:
X<int> x = new X<int> { { 10, 20, 30}, {40, 50, 60} };
But in a member or collection initializer context this is not a legal array property initializer:
new A() {
arr = { 10, 20, 30 }
}
(Note that I summarize and comment on the rules for arrays here https://stackoverflow.com/a/5678393/88656)
The question, as I understand it, is "why not?"
The answer is "no good reason". It's simply an oddity of the C# grammar and the rules for object and collection initializers.
I many times considered fixing this oddity but there was always something better to do with my time; it's a fix that benefits basically no one because the workaround is so easy.
I conjecture that there's nothing stopping the C# team from designing, specifying, implementing, testing and shipping that feature aside from the fact that there are still about a million other features that would be a better use of their time.
If you feel strongly about it, well, the compiler is open source; feel free to propose the feature and advocate for it. Or, for that matter, implement it and submit a pull request. (After you propose the feature.)
Until the feature you want is implemented you'll just have to use one of the three "expression" forms listed above. It is not burdensome to do so.
As you know C# supports variadic methods through the params keyword:
int Add(params int[] xs) {
return xs.Sum();
}
Which can then be called with any number of arguments you like:
Add(1);
Add(1, 2);
Add(1, 2, 3);
But say I want to call Add using an array of ints1. Is this possible and how (preferably without reflection)? I tried the following but they gave syntax errors (the syntax was pure guessing):
var xs = new[] { 1, 2, 3 };
Add(xs...); // doesn't work; syntax error
Add(params xs); // doesn't work; syntax error
1 My actual use-case is different but I thought this example would be less complicated.
Your method needs a return type:
int Add(params int[] xs) {
return xs.Sum();
}
And to call it with an array you just use the ordinary syntax for method calls:
int[] xs = new[] { 1, 2, 3 };
var result = Add(xs);
The params keyword basically just allows you to take advantage of a little syntactic sugar. It tells the compiler that when it sees
Add(1, 2, 3);
It should convert that to
Add(new int[] { 1, 2, 3});
So to do this from your code, you don't have to do anything special.
int[] parameters = new int[] { ... }
results = Add(parameters);
See the documentation for more details.
As far as I know, you can just call it with an array like you would a normal method:
Add(xs);
Nothing fancy, no params keyword on the method call, no dots.
static void Main(string[] args)
{
int[] tmp = {1, 2};
var sum = Add(tmp);
}
public static int Add(params int[] xs)
{
return xs.Sum();
}
Should work just fine..
If it's anything like Java, you can just call the method with the array as an argument.
This feature is also what makes varargs dangerous, especially if one of the vararg types is also an array...
I have the following situation:
A constructor takes 6 values.
Some of them have default values, some not.
#pseudocode# Foo(int a, int b=2, int c=3, int d=4, int e=5, int f){}
And I want to be able to call all possible combinations without having to write always all 6 parameters.
#pseudocode# Foo f1 = new Foo(a=1, d=7, f=6);
#pseudocode# Foo f2 = new Foo(a=1, b=9, d=7, f=6);
Besides doing this with method overloading (which would be tedious), is there a more elegant solution?
in C# 4, there are named parameters see Named and Optional Arguments (C# Programming Guide)
which would result in
new Foo(a: 1, d: 7, f: 6);
Another solution wwould be to define a Constructor with your defaut value ans use Object Initializer to set the values How to: Initialize Objects by Using an Object Initializer (C# Programming Guide)
new Foo()
{
a = 1,
d = 7,
f = 6
};
use the following for naming arguments:
Foo f1 = new Foo(a: 1, d: 7, f: 6);
Foo f2 = new Foo(a: 1, b: 9, d: 7, f: 6);
More information on Named and Optional Arguments avalable here:
http://msdn.microsoft.com/en-us/library/dd264739.aspx#Y515
I would prefer refactoring to a Parameter Object. Something like:
Foo f1 = new Foo (new FooParameters () { B = 7 })
And your FooParamaters class can encapsulate the defaults:
public class FooParameters
{
public int A { get; set; }
public int B { get; set; }
public FooParameters ()
{
A = 1;
B = 2;
}
}
2 things:
1) default parameters are left to right, once you start defaulting parameters you cannot have a non-defaulted after it, so f must have a default (in your example)
2) you can use parameter naming to skip over a default parameter:
var f1 = new Foo(5, 9, e: 9, f: 10);
This gives a =5, b = 9, c = the default, d = default, e = default, f = 10
Provided you are using C# 4.0 compiler of course...
I am new to C# (previously working on C++), I used to pass array to function with specific index. Here is the code in C++,
void MyFunc(int* arr) { /*Do something*/ }
//In other function
int myArray[10];
MyFunc(&myArray[2]);
Can I do something like this in C# .Net* ?*
As Array is Enumerable, you can make use of LINQ function Skip.
void MyFunc( int[] array ){ /*Do something*/ }
int[] myArray = { 0, 1, 2, 3, 4, 5, 6 }
MyFunc( myArray.Skip(2) );
The linq version is my preferred one. However it will prove to be very very inefficient.
You could do
int myArray[10];
int mySlice[8];
Array.Copy(myArray, 2, mySlice, 0);
and pass mySlice to the function
.NET has the System.ArraySegment<T> structure which addresses this exact use-case.
But I’ve never actually seen this structure used in code, with good reasons: it doesn’t work. Notably, it doesn’t implement any interfaces such as IEnumerable<T>. The Linq solution (= using Skip) is consequently the best alternative.
Probably the most simple way to do this is:
public void MyFunction(ref int[] data,int index)
{
data[index]=10;
}
And call it by this way:
int[] array= { 1, 2, 3, 4, 5 };
Myfunction(ref array,2);
foreach(int num in array)
Console.WriteLine(num);
This will print 1,2,10,4,5
public void MyFunc(ref int[] arr)
{
// Do something
}
int[] myArray = .... ;
MyFunc(ref myArray);
See here for more information on ref!
This is my question:
Let's say I have a class with such a constructor:
Class A {
private int i;
public A(int new_i) {
i = new_i;
}
}
Can I initialize an array of A with an array of int?
If so, how can I do it?
I was thinking something like:
int[] b = new int[5] { 0,1,2,3,4};
A[] a;
a = new A[](b);
Thanks!
var a = Array.ConvertAll(b, item => new A(item));
The advantage here is that it will be created with the right size, without any intermediate steps - plus it works without LINQ.
In C# 2.0 it is a bit uglier - the following is identical:
A[] a = Array.ConvertAll<int,A>(b,
delegate(int item) { return new A(item); });
The combination of var, lambdas, and improved generic type inference really shine for C# 3.0 here.
You could use LINQ:
int[] b = new int[5] { 0, 1, 2, 3, 4 };
A[] a = b.Select(x => new A(x)).ToArray();