I have noticed something odd with linq and the Contains method. It seems to get confused on which Contains method to call.
if (myString.Contains(strVar, StringComparison.OrdinalIgnoreCase))
{
// Code here
}
The above code doesn't compile with the following error:
The type arguments for method 'System.Linq.Enumerable.Contains(System.Collections.Generic.IEnumerable, TSource, System.Collections.Generic.IEqualityComparer)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
If I remove the using linq statement it is happy with the contains (but brakes all the linq code).
What is the correct syntax to tell the compiler I want to use the String.Contains method and not Linqs?
Cheers
This is because there's no String.Contains(string, StringComparison) method defined in the BCL and the compiler tries to use an extension method. There's only String.Contains(string) method defined.
What is the correct syntax to tell the compiler I want to use the String.Contains method and not Linqs?
There is no overload of String.Contains that accepts a StringComparision. You might want to use String.IndexOf(string, StringComparison):
// s is string
if(s.IndexOf(strVar, StringComparison.OrdinalIgnoreCase) >= 0) {
// code here
}
It could be because the string.Contains method takes only one parameter (a string; there is no overload of string.Contains that takes a StringComparison value), while the Enumarable.Contains extension method takes two. However, the parameters that you supply do not fit the expected input types, so the compiler gets confused.
As Darin Dimitrov said, String.Contains(string, StringComparison) does not exist as a method for the String type.
System.Linq.Enumerable however does contain such a signature. And a string is also an IEnumerable<char>, that's why the compiler gets confused. You would actually be able to leverage Linq and compile if you replaced the StringCompar-ison with an ICompar-er of Char:
if (myString.Contains(strVar, Comparer<Char>.Default))
{
// Code here
}
Related
I found this sample of code on SO (can't remember from where :/) that allowed me to check for line code arguments when launching my application :
if (e.Args.Length == 0 || e.Args.Any("-show".Contains))
{
//show interface...
}
I just can't seem to understand how the "-show".Contains works.
And if there's any difference with a (classic) x => x.Contains('"-show") (except for the evident typing gain).
Works like a charm but I'd like to understand why, I feel like something big is hapening.
This:
.Any("-show".Contains)
is basically shorthand for this:
.Any(s => "-show".Contains(s))
The Any method takes a delegate as a parameter and you can create that delegate in a number of ways. The first snippet uses a method group while the second uses a Lambda.
It's not really accurate to say that the first is shorthand for the second because method groups predate Lambdas, but if you think in terms of Lambdas when calling LINQ methods like Any then it is effectively the case.
As #jmcilhiney already said, it shorthand for:
.Any(s => "-show".Contains(s))
Contains is a function accepting 1 parameter which is of type string (and returns a boolean). Any() in this case wants a function that needs 1 param which is a string and that returns a boolean. So rather than adding an extra lambda warapper s=>, you can directly return .Contains
In technical terms this is a:
Func<string, boolean> //1 param string, output: boolean
Note that this code matches any argument that is a part of -show
thus either of the following arguments do match!
-show
-s
sh
ow
h
w
// etc..
Any() expects a Func<TSource, bool> delegate. So any function that returns a bool and takes an argument that is of the same type as the elements of the collection (string in your case) can be applied. This can be an existing function, or a lambda expression.
The signature of String.Contains is
bool Contains(string s)
That's why you can pass it to Any()
The equivalent would be x => "-show".Contains(x) rather than what you've shown.
After that you'll realise that all you're doing by introducing the x based lambda is to create a function accepting a single string argument and returning a bool and wrapping a function that accepts a single string and returns a bool. There's no need for the wrapper.
I may be stupid, but what is the difference between contains and contains<> in VS whisper help? Sometimes I get both, sometimes only the one with <>.
They things is that I am trying to use contains in where as in some solutions found here on SO, but it throws error that I best overload method has some invalid arguments (them method is System.Linq.ParallelEnumerable.Contains<TSource>(...)).
My code is like this:
defaultDL = db.SomeEntity
.Where(dl => dl.Something == this.Something
&& (dl.AllLocation == true || this.SomeOtherEntity.Select(loc => loc.Location).Contains(dl.Location)))
.ToList();
If you navigate to definition of System.Linq.Enumerable.Contains method, you will see that it is declared as generic extension method.
public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value);
The reason why sometimes it is called with <type> arguments, and sometimes not - is because most of the time compiler will analize it's arguments and determine type automatically. So under the hood, it will be rewritten to explicit generic call.
Like
someCollection.Contains(someValue);
actually is being compiled to
Enumerable.Contains<CollectionInnerType>(someCollection, someValue);
Linq has extension method Contains<>. When you are using it - you can enter type parameters, or not. If you are not enter - c# compiler will try to specify arguments implicitly.
Some other enumerable classes (e.g. List<>) implement own Contain method.
So, when IntelliSense suggest Contains<> method - it is an implementation from Linq; when Contains - it is own implementation of concrete class.
About difference in implementation. Own implementation of class seems to be faster, than Linq implementation, because Linq implementation is more abstract from endpoint class.
There are many possibilities. But here are the most common.
I'm guessing SomeOtherEntity is a reference to an ICollection<T>. That is a standard method on ICollection that scans in memory for reference equality (depending on implementation). You can read about that here.
There also is the Contains<T> which comes from LINQ. It is an extension method. It works on IEnumerable<T> which ICollection<T> is derived from. You can read about this one here.
It has the following basic difference.
Contains is an Extension method while Contains is not.
Contains retrun IEnumerable<T> while Contais return bool value and determines whether your item is present or not. In Contain you can pass deligates that based on condition will return IEnumerable<T>.
Just wondering how C# determines the order of execution on an object in Method Overload
For instance I have a Method
bool SomeMethod(IQueryable source)
{
//.... Do Work
}
bool SomeMethod(IEnumerable source)
{
//.... Do Work
}
var Obj = Db.Table.Where(ID > 5);
SomeMethod(Obj);
When I run this the code goes to the IQueryable Overload, Now is that because I declared IQueryable First, is it because IQueryable is of Type IEnumerable or is there some other underlying reason why?
-Thanks
There is a betterness algorithm (section 7.4.3 of the C# spects) for deciding which method overload to use in the event that there are multiple applicable overloads. In this case an IQueryable is implicitly convertible to an IEnumerable, but an IEnumerable is not implicitly convertible to an IQueryable, making IQueryable the "better" overload.
See Also
7.4.2.3 Better conversion
.NET compiler is always looking for a most specific overload. Suppose you have a simple function that accepts a single parameter, with overloads for object and string parameters. If you are passing a string, string is an object, but string overload is more specific, so it will be called. With complex function signatures and many overloads sometimes you get compiler error "not most specific". See also:
Overload resolution failed because no accessible 'method' is most specific for these arguments:error
I have a statement like so:
var vals =
from StandAloneUserPayment saup in _Session.Query<StandAloneUserPayment>()
.Fetch(x => x.RecurringPayments)
where
saup.User.UserId == userId
&& searchString.Contains(saup.FriendlyName, StringComparer.InvariantCultureIgnoreCase)
select
saup;
This seems to be exactly what I'm supposed to do, but I get the whole line with the Contains method underlined with the following message:
string does not contain a definition for Contains and the best extension method overload System.Linq.ParallelEnumerable.Contains<TSource>(System.Linq.ParallelQuery<TSource>, TSource, System.Collections.Generic.IEqualityComparer<TSource>) has some invalid arguments
What am I doing wrong?
Try IndexOf:
searchString.IndexOf(saup.FriendlyName,
StringComparison.InvariantCultureIgnoreCase) != -1
The reason it doesn't work is because the Contains extension method that accepts an IEqualityComparer<TSource> is operating on a String, which implements IEnumerable<char>, not IEnumerable<string>, so a string and an IEqualityComparer<string> can't be passed to it.
Even if there is a Contains(source, item, comparer) method, you can't* use that with NHibernate, as comparers are code, not expression trees that NH can translate.
*: that is, unless you write a LINQ provider extension that special-cases generation for your comparer, but that's not the case.
The .Contains you are using comes from LINQ - it sees the String as an IEnumerable<char>, so it wants an IEqualityComparer<char>. The StringComparer comparers implement IEqualityComparer<String>.
If minitech's IndexOf method works, I think that will be the easiest way.
Add following namespace to your class,
using System.Linq;
Hope it helps.
I'm looking for a good explanation why one piece of code fails to compile and the other compiles just fine.
Fails:
richTextBox1.Invoke(new MethodInvoker((() => { richTextBox1.AppendText("test"); })));
Gives the error
Method name expected
on the opening parenthesis right after MethodInvoker(. Apparently, I can't wrap my lambda statements in parentheses.
Compiles:
richTextBox1.Invoke(new MethodInvoker(() => { richTextBox1.AppendText("test"); }));
The questions is - why?
I always took it for granted that I could wrap any method param in parentheses if I wanted but apparently that's not the case with lambda expressions. I understand that they are somewhat special, but I still can't see a good reason for this. Maybe I don't understand something about the syntax. I would really like to get it.
By the way, this presents in VS2008, .NET 3.5 SP1, I haven't tested it in VS2010 and .NET 4 yet.
It's not a lambda expression, it's a parenthesized expression that contains a lambda expression. Therefore, the node for this parameter in the abstract syntax tree for this method invocation would be a parenthesized expression, and not a lambda expression as required by the specification. This is why.
There are other places where the Microsoft C# compiler does violate the specification and accept such an expression even though it shouldn't (per the specification) but this is not one of them.
The relevant section of the specification is §6.5.
You are mistaken in the premise that you have written a “method param”. The construct you have created is not a method call, you have written a delegate creation expression (see the C# specification, section 7.6.10.5), which is supposed to have a single argument, which must be either
a method group,
an anonymous function or
a value of either the compile time type dynamic or a delegate-type.
In your case, it is not a method group (the error message is hinting that a method name is expected there), nor an anonymous function (since it is an expression which “somewhere inside” contains an anonymous function), nor a value of the said types.
If you wrote a method invokation, you could, indeed, wrap the parameter in parentheses, even if it contains a lambda expression:
void Method(Action action)
{
}
...
Method((() => { Console.WriteLine("OK"); }));
Because the compiler expects ()=>{} inside the Invoke() method and in the first example it does not find it. Everything within the parenthesis is evaluated first returning a single object, at which case the compiler expects the reference to a delegate.
Edited
I have solved the same problem with this Extension method:
public delegate void EmptyHandler();
public static void SafeCall(this Control control, EmptyHandler method)
{
if (control.InvokeRequired)
{
control.Invoke(method);
}
else
{
method();
}
}
So you can call
RichTextBox rtb = new RichRextBox();
...
rtb.SafeCall( ()=> rtb.AppendText("test") );