C# Sort, cannot convert lambda expression to System.Array - c#

Based on what I've found on .Sort() this should work
using System;
using System.Linq;
public class Test
{
public static void Main()
{
int[] test = new int[] {6, 2, 1, 4, 9, 3, 7};
test.Sort((a,b) => a<b);
}
}
However, I'm getting this error message:
error CS1660: Cannot convert `lambda expression' to non-delegate type `System.Array'
That's the simplest version I could find to get that error. In my case, I'm taking a string, giving it a complex ranking value, and comparing that.
What am I missing here?

The overload of Sort that you are after expects a delegate that takes in two objects of the type contained within the array, and returns an int. You need to change your expression to return an int, where you return a negative value for items that come before the other, zero when the items are "equal", and a positive value for items that come after the other.
Also, for arrays the Sort method is static, so you call it using the class name, not as an instance:
Array.Sort(test, (left, right) => left.CompareTo(right));
CompareTo is a built-in function on types that are IComparable (like int), and it returns an int in the manner I described above, so it is convenient to use for sorting.

Related

How can I parse a string that represents a chain of generic methods?

In my app I need to parse a string like this, ".Add(20).Subtract(10).Add(2)" in a generic way into a series of method calls. In code I will supply the user with a value of T, and then expect the user to type an expression of the above format to calculate a new T from the expression. In the above example, I show the user an int and they typed the above string.
I need to aggregate any number of these chained string-representation of method calls into one cache-able property (delegate? Func<T,T>?) so that whenever a new value of T comes along it can be passed through the cached expression.
I initially thought there would be a way to aggregate these like a functional-programming pipeline, the outcome being a Func<T,T> that could represent the pipeline of methods. I'm guaranteed to know typeof(T) beforehand.
I'm hitting issues. Here's where I'm at:
I can regex the string with
\.(?<expName>[A-Z,a-z]+)\((?<expValue>[^)]+)\)
To get these matches:
expName
expValue
"Add"
"20"
"Subtract"
"10"
"Add"
"2"
I was expecting to use a TypeConverter to parse all expValue matches but I realized that given an arbitrary method T Foo(object arg) the arg can be any type to be determined by the specific method. The only guarantee is that a T input should always result in a T output.
We already know what type T is so we can theoretically map typeof(T) to a set of strings representing method names. I tried creating Dictionaries like this:
public static readonly Dictionary<string, Func<double, double, double>> DoubleMethods = new Dictionary<string, Func<double, double, double>>()
{
{"Add",(d,v)=>d+v },
{"Subtract",(d,v)=>d-v },
{"Multiply",(d,v)=>d*v },
{"Divide",(d,v)=>d/v }
};
public static Dictionary<string, Func<T, T, T>> TypeMethods<T>(Type t)
{
if(t.GetType() == typeof(double)) { return DoubleMethods; }
}
This won't compile, as I can't mix generics like this.
How do I create a linking structure that maps strings of predefined method names to a method, and then pass it the arg?
I also see that I will incur a bunch of boxing/unboxing penalties for arguments that happen to be primitive types, as in the example int.Add(int addedVal) method.
I believe I'm delving into parser/lexer territory without much familiarity.
Can you give an example of some code to point me in the right direction?
I'm not sure I see the need for the generics part:
var ops = "Add(20).Subtract(10).Divide(2).Multiply(5)";//25
var res = ops
.Split("().".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
.Chunk(2)
.Aggregate(0.0,(r,arr)=> r = DoubleMethods[arr[0]](r, double.Parse(arr[1])));
All those inputs parse as double, so let's just break the input string into chunks of 2 after splitting on the punctuation:
Add 20
Subtract 10
Divide 2
Multiply 5
Then run an agg op where we start from 0 (I wanted to start from 20 actually so that is what the add 20 is for)
The agg op looks up the method to call in the dictionary using the first element of the chunk
DoubleMethods[arr[0]]
And calls it passing in the current accumulator value r and the double parsing of the second element of the chunk:
(r, double.Parse(arr[1]))
and store the result into the accumulator for passing into the next op
I commented "do it in decimal" because it doesn't have floating point imprecision, but I used double just because your code did; you could swap to using decimal if you like, main point being that I can't see why you're worried about generics when decimal/double can store values one would encounter in ints too.
//basevalue is the value of the code your applying the change to.
soo... lets pretend the class is called number
Number ect = new Number(startingAmount)
in number we would have startingAmount = this.baseValue
public static T add(T baseValue, T change){
return baseValue+change;
}
public static T subtract(T baseValue, T change){
return baseValue-change;
}
public static T multiply(T baseValue, T change){
return baseValue*change;
}
public static T divide(T baseValue, T change){
return baseValue/change;
}
This should work... At least I hope it does
Here is a video on generics https://www.youtube.com/watch?v=K1iu1kXkVoA&t=1s
Java == c# so everything should be almost exactly the same

C# Cannot use Linq DefaultIfEmpty in ushort list items?

I want to take max value of ushort list and when that list is empty I want set "1" for default value.
For example:
List<ushort> takeMaxmumId = new List<ushort>();
var max = takeMaxmumId.Select(x=>x).DefaultIfEmpty(1).Max();
In my Example Visual Studio Show me this error:
'IEnumerable' does not contain a definition for
'DefaultIfEmpty' and the best extension method overload
'Queryable.DefaultIfEmpty(IQueryable, int)' requires a
receiver of type 'IQueryable'
When my list type were int I have not any problem, What is this problem in ushort type? And how can I fix this with best way?
The problem is that Select produces an IEnumerable<ushort>, while DefaultIfEmpty supplies an int default. Hence, the types do not match.
You can fix this by forcing ushort type on the default:
var max = takeMaxmumId.Select(x=>x).DefaultIfEmpty<ushort>(1).Max();
// ^^^^^^^^^^^^^
// This part can be removed
Demo.
You can also convert sequence elements to int:
var max = takeMaxmumId.Select(x => (int)x).DefaultIfEmpty(1).Max();
Since your data type is ushort you will have to staisfy the alternative orverload of DefaultIfEmpty extension method. i.e DefaultIfEmpty(this IEnumerable source, TSource defaultValue);
So you will have to cast to your source to type ushort.
var max = takeMaxmumId.Select(x => x).DefaultIfEmpty( (ushort) 1).Max();
You could try this one:
var max = takeMaximumId.DefaultIfEmpty((ushort)1).Select(x => x).Max();
The problem is due to the fact that passing 1 without the cast to ushort you can't apply the extension method DefaultIfEmpty, because 1 is interpreted as int and the list you want to apply this is of type List<ushort>. If you write the following
var max = takeMaximumId.DefaultIfEmpty(1).Select(x => x).Max();
you would get the error message below, which explains the above
statement:
'List' does not contain a definition for 'DefaultIfEmpty' and
the best extension method overload
'Queryable.DefaultIfEmpty(IQueryable, int)' requires a
receiver of type 'IQueryable'
As a side note, despite the fact that dasblinkenlight has already mentioned this in his post, you don't need at all the Select, since you don't make any projection there. You just want to get the maximum value of the numbers contained in your list.

What is the difference between myArray.GetValue(2) and myArray[2] in C#?

Is there any difference between using myArray.GetValue(2) and myArray[2]?
For example:
namespace ConsoleApplication16
{
class Program
{
static void Main(string[] args)
{
int[] numbers = new int[] { 1, 2, 3, 4 };
Console.WriteLine(numbers.GetValue(3));
Console.WriteLine(numbers[3]);
Console.ReadLine();
}
}
}
GetValue will return type object while using the index will return the type specific with the array.
You can see in this fiddle (code below) that the variable val1 can have a string stored in it, but val2 can only be used as an integer.
public static void Main()
{
int[] numbers = new int[]{1, 2, 3, 4};
var val1 = numbers.GetValue(3);
var type = val1.GetType();
var val2 = numbers[3];
Console.WriteLine(type.ToString());
val1 = "hello";
type = val1.GetType();
Console.WriteLine(type.ToString());
}
This will result in boxing and unboxing, which won't have an effect on a small code snippet, but if used in large scale it could potentially affect performance.
In your code, there isn't a difference. The primary difference, inside an array when you call Array.GetValue(1) you're receiving the value of that index. You can't specifically set the value of the array though.
If you were to do Array[1] = "..."; you've modified the array. But you can also still attain the value, though it may not be as expressive as above. So you can get or set a value with this approach.
The number of elements in indices must equal the number of dimensions
in the Array. All elements in the indices array must collectively
specify the position of the desired element in the multidimensional
Array. The GetLowerBound and GetUpperBound methods can determine
whether any of the indexes is out of bounds. This method is an O(1)
operation.
Both are susceptible do the above though.
numbers.GetValue(3) returns an object and therefor the overload Console.WriteLine(object value) that takes an object parameter is called.
numbers[3] is of type int and then Console.WriteLine(int value) that takes an int as parameter is called.
So you end up calling different methods.
When you are using Array class(with uppercase) there are not indexers. So the way you can get and set elements on it is using GetValue() or SetValue()
See this link : Using an array's SetValue method vs. the [] indexers
In use-ability there isn't a difference except for setting values. The difference however seems to be in how it gets the value.
Array's .GetValue gives me this, it returns an object.
Either approach takes under 1ms so there isn't a substantial speed difference either.

Can params[] be parameters for a lambda expression? [duplicate]

This question already has answers here:
Variable parameters in C# Lambda
(5 answers)
Closed 1 year ago.
I've recently started exploring lambda expressions, and a question came to mind. Say I have a function that requires an indeterminate number of parameters. I would use the params keyword to model that variable number of parameters.
My question: can I do something similar with Lambda expressions? For example:
Func<int[], int> foo = (params numbers[]) =>
{
int result;
foreach(int number in numbers)
{
result += numbers;
}
return result;
}
If so, two sub-questions present themselves - is there a 'good' way to write such an expression, and would I even want to write an expression like this at some point?
Well, sort of.
First, instead of using Func<>, you would need to define a custom delegate:
public delegate int ParamsFunc (params int[] numbers);
Then, you could write a following lambda:
ParamsFunc sum = p => p.Sum();
And invoke it with variable number of arguments:
Console.WriteLine(sum(1, 2, 3));
Console.WriteLine(sum(1, 2, 3, 4));
Console.WriteLine(sum(1, 2, 3, 4, 5));
But to be honest, it is really much more straightforward to stick with built-in Func<> delegates.
The closest thing that I think you can get would be something like this:
Func<int[], int> foo = numbers[] =>
{
// logic...
}
var result = foo(Params.Get(1, 5, 4, 4, 36, 321, 21, 2, 0, -4));
And have:
public static class Params
{
public static T[] Get(params T[] arr)
{
return arr;
}
}
But I can't see how that beats a simple new[] {1, 5, 4, 4, ...}
There are two things here, the Func<int[], int> generic delegate on the LHS and the lambda expression on the RHS. The former is not possible, since a Func<S, T> delegate is declared like:
public delegate TResult Func<in T, out TResult>(T arg); //ie no params involved
You need your own delegate that accepts params input as shown in accepted answer.
The latter, which is what the question title is about, is not possible as well in C#, but for a reason.
The LHS of an assignment expression is a compile time thing (unless it's dynamic of course but again compiler is aware of it) and its RHS is a run time thing (unless of course in case of consts). The compiler can infer what's typed on LHS, but it gets the values on RHS only during run time, ie when the code is run. When you type this:
Func<int[], int> foo = ....
foo is always considered as Func<int[], int>. It will add a lot of complexity to compiler if it had to decipher RHS. For e.g. if what you're attempting was possible, think about this scenario:
Func<int[], int> foo = (params int[] numbers) =>
{
int result;
foreach(int number in numbers)
{
result += numbers;
}
return result;
};
//and later at some other place
foo = (int[] numbers) => 0;
//how would you call 'foo' now?
Instead when you write your own delegate that accepts params, you're telling the compiler directly (ie known from LHS).
Of the three features that parameters of a named method support, ie, out/ref, params, optional parameter, lambda expressions (or even the earlier delegate syntax) support only out/ref.

What is actually happening with IQueryable.Where()?

This is is returning a boolean based on whether or not there are some matching IDs.
from t in getAll
select new Result
{
...
bool DetailsAvailable =
(db.SaveTrackings.Where(s => s.BundleID == t.bundleID
&& s.UserID == t.userID)
.Count() > 0) ? true : false;
}
This is what I think understand: .Where() is returning all the entries with the matching IDs and then the .Count() is just seeing how many are there. I only feel like I half understand what we need s for.
I know what to expect from this code since it's been in use I just don't understand how it works and some of the documentation from MSDN is using some terminology that is confusing me.
All lambda expressions use the lambda
operator =>, which is read as "goes
to". The left side of the lambda
operator specifies the input
parameters (if any) and the right side
holds the expression or statement
block. The lambda expression x => x *
x is read "x goes to x times x."
So how am I suppose to understand what my code means based on this, .Where(s "goes to" s.BundleID == t.BundleID...) so what's happening here? What does "goes to" mean? Is it comparing every ID in s to everyone one available in t? How do I understand why it's called "goes to" and what exactly is happening?
And then it gets more confusing...
The => operator has the same
precedence as assignment (=) and is
right-associative.
Lambdas are used in method-based LINQ
queries as arguments to standard query
operator methods such as Where.
When you use method-based syntax to
call the Where method in the
Enumerable class (as you do in LINQ to
Objects and LINQ to XML) the parameter
is a delegate type System.Func. A lambda expression is the
most convenient way to create that
delegate.
What is a delegate type System.Func<T, TResult> and how is it created with this "goes to" operator?
I can't just use code because I know that it's working, I need to understand how/why.
Maybe it would help to see this function implemented by hand:
using System;
using System.Collections.Generic;
namespace CSharpSandbox
{
class Program
{
static IEnumerable<T> Where<T>(IEnumerable<T> input, Func<T, bool> predicate)
{
foreach (T item in input)
{
if (predicate(item))
yield return item;
}
}
static void Main(string[] args)
{
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<int> evens = Where(numbers, n => n % 2 == 0);
foreach (int even in evens)
{
Console.WriteLine(even);
}
}
}
}
The construct name => someEvaluation creates an anonymous function consisting of the following parts:
name is simply the name of a parameter, its type is inferred from its usage. You need a name so you can refer to the argument passed in the function.
=> is the start of your anonymous functions body, the scope of the body is a single expression.
someEvaluation is the body of your anonymous function composed of a single expression.
In our case, Func<T, bool> defines a function which takes a single parameter of type T and returns an output of type bool. (If we had used Func<T, U, bool>, we'd take two inputs of type T and U and return a bool. The last type parameter in the Func definition is the return value.)
You can invoke an instance of Func exactly as you invoke any other function. If the func takes params, you pass them in as expected, your parameters are bound to the variable names you defined. When you invoke the function, control flow will jump inside your function and evaluate its results.
In principle, you don't need to create a Func anonymously. You can pass in any function which has a compatible type signature, such as:
static bool IsEven(int n)
{
return n % 2 == 0;
}
static void Main(string[] args)
{
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IEnumerable<int> evens = Where(numbers, IsEven);
foreach (int even in evens)
{
Console.WriteLine(even);
}
}
This program produces the same output. In fact, behind the scenes, the syntax name => expression is syntax sugar; when it gets compiled, C# will produce a produce a private function with a hidden name and convert it to the format above.
If it helps, think of s as a variable of type SaveTracking. It's iterating over each s in your collection/table, and testing the value of its BundleID.
The t is same idea - it's like it's iterating through all the return collection from the getAll.
It's like the SQL pseudocode:
SELECT * FROM SaveTracking INNER JOIN GetAll
ON BundleID AND UserID
For a deeper technical description of what's going on with lambda expressions, check out Jon Skeet's book C# In Depth. Chapter 9 , p 230. I found this book very helpful.
Lambda expressions are just a way to shorten the code but it does exactly the same things as declaring a method that corresponds to the delegate type System.Func<T, TResult>
I believe that C# converts your lamba to a method in the background when you compile and it looks like this :
bool LambdaExpression(YourType s)
{
return s.BundleID == t.bundleID && s.UserID == t.userID;
}

Categories

Resources