int.Parse method without parentheses - c#

Why can I invoke Parse method without parentheses since that method has 4 overloads?
For example in this case:
string[] aTemp = Console.ReadLine().Split(' ');
int[] a = Array.ConvertAll(aTemp, int.Parse);

The signature for ConvertAll is actually this:
public static TOutput[] ConvertAll<TInput, TOutput>(
TInput[] array,
Converter<TInput, TOutput> converter
)
Which the compiler can infer to be:
public static int[] ConvertAll<string, int>(
string[] array,
Converter<string, int> converter
)
From the signature for Int32.Parse:
public static int Parse(
string s
)
If you wanted to write out in long hand:
Converter<string, int> converter = new Converter<string, int>(Int32.Parse);
string[] aTemp = Console.ReadLine().Split(' ');
int[] a = Array.ConvertAll<string, int>(aTemp, converter);
Note: Converter<TInput, TOutput> is actually a delegate that takes as input a parameter of type TInput and returns a value of type TOutput.

Array.ConvertAll takes two parameters, an array of TInput, and a converter delegate from TInput to TOutput. There's only one overload of int.Parse that matches the signature of a converter delegate -
public static int Parse(
string s
)
Putting together all of the information available, we can pick the right method to call.

Related

What does GenericType<(param1, param2...)> means

I have been on that link but there are some lines I really don't understand.
1) List<()>
private readonly List<(string MemberName, Func<T, object> Fingerprint)> _fingerprints;
2) For < Tproperty>
public FingerprintBuilder<T> For<TProperty>(Expression<Func<T, TProperty>> memberExpression, Expression<Func<TProperty, TProperty>> fingerprint
How are they called? Can you provide some good links/explanations about them?
When you see
Func<T, TProperty> that is a delegate fingerprint, last item under <> is output, all others inputs.
So
Func<string, string, int> Fcn
Is a function that accepts 2 string parameters and returns integer value.
Lets define a function that accepts 2 strings and returns sum of their lengths
Func<string, string, int> Fcn = (string s1, string s2) => s1.Length + s2.Length;
var result = Fcn.Invoke("test", "test2");
Console.WriteLine(result); // will return 9
In your case, it is just some generic types, but functionally it is the same like this example

C# notation understanding Select(int.Parse)

I found a little script that I understand fully. I've got a string with "1 -2 5 40" for example. It reads the input string, splits it into a temporary array. Then this array is parsed and each element is transformed into an integer. The whole thing is order to give the nearest integer to zero.
But what I don't understand is the notation Select(int.Parse). There is no lambda expression here and the method int.Parse isn't called with brackets. Same with the OrderBy(Math.Abs)
Thank you in advance =)
var temps = Console.ReadLine().Split(new []{' '}, StringSplitOptions.RemoveEmptyEntries);
var result = temps.Select(int.Parse)
.OrderBy(Math.Abs)
.ThenByDescending(x => x)
.FirstOrDefault();
int.Parse is a method group - what you're seeing is a method group conversion to a delegate. To see it without LINQ:
Func<string, int> parser = int.Parse;
int x = parser("10"); // x=10
It's mostly equivalent to:
Func<string, int> parser = text => int.Parse(text);
... although there are plenty of differences if you want to go into the details :)
Select(int.Parse) is nearly equivalent to Select(x => int.Parse(x)).
The Select demands an Func<T, R>, which in this case is also the signature of int.Parse (it has a single parameter with a return value). It convers the method group to the matching delegate.
In this case Func<T, R> will map to Func<string, int>, so it matches the int Parse(string) signature.
int.Parse is a method with signature string -> int (or actually, a method group, with different signatures. But the compiler can infer you need this one, because it is the only one that fits.
You could use this method as a parameter wherever you would supply a delegate parameter with the same signature.
The parameter for .Select() is Func<T1, T2>() where T1 is the input parameter (the individual values of temps), and T2 is the return type.
Typically, this is written as a lambda function: x => return x + 1, etc. However, any method that fits the generic definitions can be used without having to be written as a lambda since the method name is the same as assigning the lambda to a variable.
So Func<string, int> parseInt = s => Convert.ToInt32(s); is syntactically equivalent to calling the method int.Parse(s).
The language creates the shortcut of automatically passing the Func parameter to the inside method to create more readable code.
Select LINQ IEnumerable<> extension method signature looks like that:
public static IEnumerable<TResult> Select<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector
)
Look at the selector argument. In your case you pass to Select .Net standard function int.Parse which has signature:
public static int Parse(
string s
)
.Net compiler can convert delegates to Func<...> or Action<...>. In case of int.Parse it can be converted to Func and therefore can be passed as argument to Select method.
Exactly the same with OrderBy. Look at its signature too.

Confused as to why this C# code compiles, while similar code does not

Let's take the following extension method:
static class Extensions
{
public static bool In<T>(this T t, params T[] values)
{
return false;
}
}
I'm curious as to why this code compiles and runs:
var x = new Object();
IEnumerable<int> p = new List<int> { 1, 2, 3 };
var t2 = x.In(p);
Within In, values is an Object[], as if the List<int> gets converted on the fly to an array. To me, it seems that params T[] does not match IEnumerable<int>, which is why I'm surprised this even runs.
Now this code:
var x = 5;
IEnumerable<int> p = new List<int> { 1, 2, 3 };
var t2 = x.In(p);
Does not run and generates the compiler error:
Error 2 Argument 2: cannot convert from
'System.Collections.Generic.IEnumerable' to 'int[]'
This is what I'd expect from the first one actually. Can someone explain what's going on here? Thanks!
Type inference converts your first call to
In<object>(x, p);
The parameters of this closed generic method are object, params object[].
Therefore, passing p implicitly converts it to an object, which becomes the single item in the params array.
Your second call is inferred (because of the first parameter) to
In<int>(x, p);
Here, the second parameter can either be an int[] (passing an array directly) or a series of ints (via params).
Since IEnumerable<int> is neither of those, you get an error.

Implementing generics in a function using Func

I have a follow static function:
public static string codeList<T>(List<T> thelist, Func<T, string> coder);
using this function with my own objects is not problem for example:
string code = codeList<MyClass>(myclassList, MyClass.code);
Where MyClass.code is a static function (defined in MyClass) that gets MyClass and returns string.
The problem is when I try to use this function with List<int> or List<double> what I do now is predefining statics like Func<int,string> intCoder = (x) => x.ToString(); and Func<double,string> (x) => x.ToString(); and use them.
Is there another way of doing that? something like:
string code = codeList<int>(intList, Int32.ToString);
You can do this with
string code = codeList<int>(intList, Convert.ToString);
It just so happens that Convert.ToString has an overload with the appropriate signature.
The problem with int.ToString is that none of its overloads have the appropriate signature (they don't take an int parameter as it is implied). In that case there would be nothing you could do apart from defining an adapter function.
You don't have to declare a variable for the func. You can just put the lambda expression as the parameter value
string code = codeList(intList, i => i.ToString());

Pass array as individual values to params

I am calling a function which takes the same form as string.format where the first parameter is a string and the remainder are the replacement values. I have the string in a variable and the replacement values in an array, how can I call this function given any number of objects in the array? Simply passing in the array as the last argument does not work.
Use the params keyword:
public string MyMethod(string value, params object[] args)
{
// as an example
return string.Format(value, args);
}
Then you can call it either with individual values
MyMethod("Test", "value1", "value2");
Or with an array
MyMethod("Test", new [] { "value1", "value2" });
you need to use the params keyword
The function I was calling had the signature
public static IQueryable Where(this IQueryable source, string predicate, params object[] values)
Thhe issue was that I was passing in an array of ints as the last parameter. When I createed a new array of objects poplulated from that initial array and passed it in it worked. Thanks for the answers

Categories

Resources