Odd Lambda Expression Question - c#

List<string> a = new List<string>() { "a", "b", "c" };
List<string> b = new List<string>() { "a", "b", "c", "d", "e", "f" };
b.RemoveAll(a.Contains);
If you loop through b it will now only contain d e and f. Can anyone expand out whats actually happening, because currently it doesnt make any sense at all.
Edit: I was more talking about the use of predicates. How does know how to pass what into where?

b.RemoveAll(<function that takes a string and returns true if we want to remove it>)
no lambda expression required.
perhaps you'd like for the line to read
b.RemoveAll(x => a.Contains(x))
however, the function x=> a.Contains(x) is simply a function that takes a string and returns a bool indicating whether a contains x. a.Contains is already a function that does that.

The { } Syntax is a collection initializer. The code is equivalent to
List<string> a = new List<string>();
a.Add("a");
a.Add("b");
a.Add("c");
List<string> b = new List<string>();
b.Add("a");
b.Add("b");
b.Add("c");
b.Add("d");
b.Add("e");
b.Add("f");
b.RemoveAll is a function that calls another function and passes in a string. It's like this:
foreach(string s in b) {
if(FunctionToCall(s) == true) b.Remove(s);
}
a.Contains is a function that takes a string and returns a bool. So the code can be changed to:
foreach(string s in b) {
if(a.Contains(s)) b.Remove(s);
}
Note that in this Lambda-Syntax, you are passing the "a.Contains" function - not the result of the function! It's like a function pointer. RemoveAll expects to take a function in the form of "bool FunctionName(string input)".
Edit: Do you know what delegates are? They are a bit like function pointers: A delegate specifies a signature ("Takes 2 strings, returns an int"), and then you can use it like a variable. If you don't know about delegates, read Karl Seguins article.
Some delegates are needed extremely often, so the .net Framework developers added three types of extremely common delegates:
Predicate: A delegate that takes a T and returns a bool.
Action: A delegate that takes 1 to 4 parameters and returns void
Function: A delegate that takes 0 to 4 parameters and returns a T
(Shamelessly copied from Jon Skeet's Answer here)
So predicate is just the name given for a delegate, so that you don't have to specify it yourself.
If you have ANY function in your assembly with the signature
"bool YourFunction(string something)", it is a Predicate<string> and can be passed into any other function that takes one:
public bool SomeFunctionUsedAsPredicate(string someInput)
{
// Perform some very specific functionality, i.e. calling a web
// service to look up stuff in a database and decide if someInput is good
return true;
}
// This Function is very generic - it does not know how to check if someInput
// is good, but it knows what to do once it has found out if someInput is good or not
public string SomeVeryGenericFunction(string someInput, Predicate<string> someDelegate)
{
if (someDelegate.Invoke(someInput) == true)
{
return "Yup, that's true!";
}
else
{
return "Nope, that was false!";
}
}
public void YourCallingFunction()
{
string result = SomeVeryGenericFunction("bla", SomeFunctionUsedAsPredicate);
}
The whole point is separation of concerns (see the comment in SomeGenericFunction) and also to have very generic functions. Look at my generic, extensible string encoding function. This uses the Func rather than the Predicate delegate, but the purpose is the same.

look at it like this:
foreach(string s in b)
{
if(a.Contains(s))
b.Remove(s);
}
You passing the bit in the if evaluation clause as a delegate (managed equivalent of a function pointer). The RemoveAll method unrolls the list and does the rest.

It says 'remove all elements in b that are contained in a'. So you're left only with the one's in b that weren't also present in a.

Here is a slightly expanded version of your code that shows what's happening:
List<string> a = new List<string> () { "a", "b", "c" };
List<string> b = new List<string> () { "a", "b", "c", "d", "e", "f" };
Predicate<string> ps = a.Contains;
b.RemoveAll (ps);

For every element in b, a.Contains() is being evaluated for that element. If it's true, it is removed.
So, you're removing every element from b that is also contained in a.
The function "a.Contains" is being passed as an argument to RemoveAll.

The signature for RemoveAll looks like this ...
public int RemoveAll(Predicate<T> match);
A Predicate<T> is a delegate that takes Ts and returns bools ...
public delegate bool Predicate<T>(T obj)
RemoveAll is thus asking for a reference to a method that will, in your case, take strings and return bools. List<T>.Contains is such a method. You will note that the signature for List<T>.Contains matches the Predicate delegate (it takes Ts and returns bools) ...
public bool Contains(T item);
RemoveAll will apply whatever Predicate is passed as "match" to each element of the list upon which it is called (b in your case). So, if a.Contains("a"), for example, returns true, then all the a's will be removed from the b list. Thus, in your example, all the a's, b's and c's are removed.
Using a tool like .NET Reflector will let you look at the code of RemoveAll and that might help clarify what's happening under the covers.

Related

Array initialization syntax in method call

Having the code below, why is the variable declaration considered as correct syntax, but not also the method call?
public static void Func(string[] p)
{
}
public static void Test()
{
string[] a = { "x", "y", "z" };
Func({"x", "y", "z"});
}
It looks like everybody else is focusing on the workaround (which is simply to specify that you need a new [] { "some", "strings" }. The why is a little less obvious though.
The former is valid because the compiler knows to use your initialization syntax to create an Array (because you've defined it as such).
The later would have some issues. It may seem trivial in this case because the compiler should, theoretically, be able to figure out that you need a string[]. Think about cases where you have a Func<IEnumerable<string>> though. What type gets generated in that case? Would the compiler take a wild-ass guess? Always use an Array (even though there might be a better fit)? It could be one of a number of possibilities.
I'm guessing that's the reason that the language specification doesn't allow for passing things this way.
You need to pass in a value as the argument. {"x", "y", "z"} is not a value. It can be used as short-hand for initializing a variable.
Note that both of these are valid:
List<string> a = new List<string>() {"x", "y", "z"};
string[] b = new string[] {"x", "y", "z"};
And the full version of what it represents:
List<string> a = new List<string>();
a.Add("x");
a.Add("y");
a.Add("z");
So you need to make an object (new)
new [] {"x", "y", "z"}
Or make an object beforehand and pass that in.
As for why this is like this, you need to pass in a value, not a helper for array initialization.
You can initialize the object directly on the inside of the method call, but do not think a good practice.
where you used:
 
Func ({"x", "y", "z"});
The above form you tried to pass an object not instantiated, ie it does not already exist on your "context". The correct is you initialize it to be generated in a reference memory to this value and thus the "Func" method you can use it.
In the case of variable declaration:
string[] a = {"x", "y", "z"};
In this case your compiler is reading:
string[] a = new string[] {"x", "y", "z"};
It does this interpretation alone, without requiring you to do object initialization explicitly.
So my answer is best for this situation you must first create the object then pass it as a parameter to the method:
 
string[] a = {"x", "y", "z"};
  Func (s);

How to call a method with the C# collection initializer?

Case
This morning I refactored some Logging method and needed to change a method's 'params' parameter in a normal array. Consequently, the call to the method had to change with an array parameter. I'd like the method call to change as less as possible, since it's a heavily used utility method.
I assumed I should be able to use the collection initializer to call the method, but it gave me a compile-error. See the second call in the example below. The third call would be fine too, but also results in an error.
Example
void Main()
{
// This works.
object[] t1 = { 1, "A", 2d };
Test(t1);
// This does not work. Syntax error: Invalid expression term '{'.
Test({1, "A", 2d });
// This does not work. Syntax error: No best type found for implicitly-typed array.
Test(new[] { 1, "A", 2d });
// This works.
Test(new object[] { 1, "A", 2d });
}
void Test(object[] test)
{
Console.WriteLine(test);
}
Question
Is there any way to call Test() without initializing an array first?
The problem is that C# is trying infer the type of the array. However, you provided values of different types and thus C# cannot infer the type. Either ensures that all you values are of the same type, or explicitly state the type when you initialize the array
var first = new []{"string", "string2", "string3"};
var second = new object[]{0.0, 0, "string"};
Once you stop using params there is no way back. You will be forced to initialize an array.
Alternative continue using params:
public void Test([CallerMemberName]string callerMemberName = null, params object[] test2){}

Implicit cast an object to an array with one element. Is it possible?

Can I implicitly create an array from one single element in C#?
For instance, I have this method
public void MyMethod(string[] arrayString)
At some point in my code I have
string str = "myStr";
MyMethod(str)
Of course the second linhe is an error, because I am passing a string while MyMethod expects a string[].
Is there any clean way to call MyMethod without using
MyMethod(new string[] {str})
If you use a params array, this will be fine:
public void MyMethod(params string[] arrayString)
string str = "myStr";
MyMethod(str)
The only way I know would be to overload the method, so that you also have
MyMethod(string)
{
return MyMethod(new string[] {str});
}
You might be able to do it with a params array, but I'm not entirely sure how that would work if you tried to pass in a string array, rather than multiple strings.
I would just add a second overload of MyMethod
public void MyMethod(string str)
{
MyMethod(new[]{str});
}
For the sake of completeness, here's another couple of options, though surely not recommended -- I'd use params as in the accepted answer.
MyMethod(Enumerable.Repeat(str, 1).ToArray());
I've also seen this on occasion, though it's hard to justify unless you're unaware of array initializers:
T[] MakeArray<T>(params T[] elements)
{
return elements;
}
used thus:
string[] grades = MakeArray("A", "B", "C", "D", "F", "Incomplete");
or, in this case:
MyMethod(MakeArray(str));
How about an extension method?
public static T[] WrapInArray<T>(this T t)
{
return new T[]{ t };
}

Passing array of Argument into multiple parameter function in C#

Life is short
def foo(b,a,r):
# bla bla bla
pass
mylist = ['b','a','r']
foo(*mylist)
That's how passing a list of arguments into method multiple positional parameters in Python.
But in C# I found out passing an array into a parameter of array using the params keywords, like this one:
void foo(params string[] bar)
{
// bla bla bla
}
string[] mylist = {"b", "a", "r"};
foo(mylist)
Imagine how If I cannot touch the function, is there an easier way
Is there a way to do that?
Here is what I mean:
void foo (string b, string a, string r)
{
// bla bla bla
}
string[] mylist = {"b", "a", "r"};
foo(mylist[0],mylist[1],mylist[2]); // This line makes my life difficult
I search online and can't found an alternative of it. Just want to make sure that I didn't miss the hidden feature that C# provide. Who know there's such shortcut for us?
No, there is no feature in C# that allows you to do this directly. But there are some ways you can use to work around that:
Create a method that converts a method with several parameters into a method with one array parameter:
static Action<T[]> ToArrayMethod<T>(Action<T, T, T> original)
{
return array => original(array[0], array[1], array[2]);
}
And then use it like this:
string[] array = {"b", "a", "r"};
var arrayFoo = ToArrayMethod(foo);
arrayFoo(array);
The downside of this approach is that this method works only on methods with exactly three parameters with a void return type. You would need to write another overload of ToArrayMethod() if you wanted this to work for methods with, say, 4 parameters, or for those that return some value.
Use reflection. When doing that, arguments are passed in using an array:
var foo = typeof(SomeType)
.GetMethod("foo", BindingFlags.Instance | BindingFlags.NonPublic);
object[] array = {"b", "a", "r"};
foo.Invoke(somTypeInstance, array);
There is downsides to using static languages, and this is one of them, if your function signature is defined as:
void foo (string a, string b, string c);
then you are forced to pass in 3 separate strings
foo(mylist[0],mylist[1],mylist[2]);
the only way to have flexible inputs in C# is by using params which you already now, or by using default values (C# 4.0):
void foo (string a, string b = null, string c = null)
meaning that if I don't pass b or c just set them to null, and now you can call your function like this:
foo(mylist[0])
You could use reflection; however, that typically isn’t recommended because it makes you sacrifice compile-time type-safety checking.
Here is a sample approach:
string[] mylist = { "b", "a", "r" };
((Action<string,string,string>)foo).DynamicInvoke(mylist);
There is no shortcut. If you want to get crazy and you're able to modify the function somewhat, you could overload it to have one signature with the params keyword, and have the original overload pass its arguments into the the new one.
So to summarize a lot of replies here, you'll need a sort of a hack for this and the cleanest way in my opinion is something along these lines:
Create an extension function for enumerables:
public static class Extensions
{
public static void SendToMethod<T>(this IEnumerable<T> self, Delegate func )
{
Contract.Requires(func.Method.GetParameters().Length == self.Count());
func.DynamicInvoke(self.Cast<object>().ToArray());
}
}
Then you can send the array to any function having an argument count equal to the length of the enumerable:
public void foo(string a, int b, bool c, string d) {}
public void foo2(string a, string b, string c) {}
...
var test1 = new object[] {"ASDF", 10, false, "QWER"};
var test2 = new[] {"A", "B", "C"};
test2.SendToMethod((Action<string, string, string>)foo);
test1.SendToMethod((Action<string, int, bool, string>)foo2);

What is Action<string>?

What is Action<string>, how can it be used?
Action is a standard delegate that has one to 4 parameters (16 in .NET 4) and doesn't return value. It's used to represent an action.
Action<String> print = (x) => Console.WriteLine(x);
List<String> names = new List<String> { "pierre", "paul", "jacques" };
names.ForEach(print);
There are other predefined delegates :
Predicate, delegate that has one parameter and returns a boolean.
Predicate<int> predicate = ((number) => number > 2);
var list = new List<int> { 1, 1, 2, 3 };
var newList = list.FindAll(predicate);
Func is the more generic one, it has 1 to 4 parameters (16 in .NET 4) and returns something
This is a delegate to a function with the signature
void Bla(string parameter). You can use this to pass functions to other functions.
For instance you can do this
Action<string> action = (x => Console.WriteLine(x));
new List<string>{"1","2","3"}.ForEach(action);
to print all characters to the console
It is a delegate with one parameter, this being a string.
Usefull because it means you do not have to create delegates anymore for actions as long as you can use a standard action for them (i.e. the number of parameters is fixed, no default values and you can just use an existing action).
public void ValidateInput(string input)
{
//some code
}
public void test()
{
Action<string> action = ValidateInput;
}
It is basically just a delegate that does not return a value.
Have a look here:
http://msdn.microsoft.com/en-us/library/018hxwa8.aspx
Action<string> would just be a delegate of a method that excepted a single string parameter and did not return anything.
here is a small and easy introduction of Action:
http://www.c-sharpcorner.com/UploadFile/rmcochran/anonymousMethods04022006141542PM/anonymousMethods.aspx

Categories