I'm sure at some point we've all written some code like this:
For Each datVehicle In datVehicles
If datVehicle.ID = -1 Then
datVehicles.Remove(datVehicle)
End If
Next
Which compiles just fine but throws runtime exception because you can't delete an item in an enumeration. Does ReSharper catch things like this?
Resharper 6.1 on VS 2010 does not catch it out-of-teh-box. Resharper does not think it is quite Skeet-code tho as it suggests converting to linq.
No version of ReSharper catches this problem. To create custom pattern that can warn about this condition is not easy because your iteration code can be pretty complex.
If you want to create a custom pattern I would suggest to create a suggestion (may be a warning). Your pattern would look something like that:
$ICOLLECTION$.Remove($arg$)
Where $ICOLLECTION$ is an expression of type System.Collections.Generic.ICollection and $arg$ is an argument placeholder.
This way you'll always have a suggestion ( or warning).
I know that the question is about ReSharper only but I want to show the workaround to complete my answer. The workaround for this problem is to use RemoveAll. Here's the example in C#:
datVehicles.RemoveAll(x => x.Id == -1);
I don't think it does automatically, but you could easily create a custom pattern to identify this for you. See: https://blog.jetbrains.com/dotnet/2010/08/19/highlighting-custom-patterns-with-resharper/
Related
I am trying to compile a Xamarin.Mac project with Monodevelop+Monomac (3.0.5 from source).
I changed the reference from XamMac to MonoMac, and everything seems to be fine except this:
Error CS0019: Operator '==' cannot be applied to operands of type 'MonoMac.Foundation.NSObject' and 'string' (CS0019)
The error occurs at a line if (tableColumn.Identifier == "Name") where tableColumn is a NSTableColumn.
Can I make this compile without modifying the code?
Or if I must modify the code, what is the best practice in this case?
surely....
if (tableColumn.Identifier.Equals("Name"))
would be better?
XamarinMac most likely has operator for == between NSString/NSObject and string. Either modify MonoMac source code to add the operator (nice chance to contribute to the community edition) or change your code to compare NSString("Name") instead of string.
I need some help with a LINQ query in VB.Net, please.
I have this simple group statement:
Dim drivers = From d In DriversOwners _
Group d By Key = d.UnitNumber Into Group _
Select Key, DriverGroup = Group
This works, and returns me the data I need to work with. Now I want to iterate through the groups, using a For Each construct. like this:
For Each x In drivers
Next
However, the compiler is barking at me, telling me that the
"'x' is not accessible in this context because it is 'Friend'."
Anyone know what I am doing wrong here?
Thanks in advance.
After digging and digging, I finally found the answer to this problem. Talk about obtuse!
Enabling LINQ in a .NET Framework 3.5 Project
When you move a project to .NET
Framework 3.5, a reference to
System.Core and a project-level import
for System.Linq (in Visual Basic only)
are added automatically. If you want
to use LINQ features, you must also
turn Option Infer on (in Visual Basic
only) [my emphasis].
When I changed the target framework from 2.0 to 3.5, Visual Studio automatically added the System.Core assembly, and automatically imported the System.Linq namespace. Now why in the world did it not also set Option Infer to "On" as well?
http://msdn.microsoft.com/en-us/library/bb398197.aspx
Looks to me like the variable x was declared earlier - as a class field, a method parameter, or a local variable.
Am I right?
I'm not sure if you've solved this or not. I had the exact same problem today and what ended up working for me was to not use a single-letter variable in the For Each loop. My code was the same as yours:
For Each x In a
...
Next
When I changed the code to the following it worked:
For Each retVal in a
...
Next
I also found the same 'Friend' error behavior for any single-letter variable.
I have no idea why it behaves this way, but I thought I'd pass this along in case this question is still out there.
Using VB.net, the following snippet gives the error below.
Dim _account = Account.Find(Function(x As Account) x.AccountName = txtFilterAccountName.Text)
or similarly if I do
.SingleOrDefault (Function(x As Account) x.AccountName = txtFilterAccountName.Text)
will both give the error "The method 'CompareString' is not supported". If I make the same call searching for an integer (ID field) it works fine.
.SingleOrDefault (Function(x As Account) x.Id = 12)
So integer matching is fine but strings don't work Is this a problem with the VB.net templates?
No this is not a problem with Vb.Net templates.
The problem is that you are not using a normal LINQ provider. Based on your tag (subsonic) I'm guessing you're using a LINQ to SQL query.
The problem is that under the hood, this is trying to turn your code into an expression tree which is then translated into an SQL like query. Your project settings are turning your string comparison into a call in the VB runtime. Specifically, Microsoft.VisualBasic.CompilerServices.Operators.CompareString.
The LINQ2SQL generater in question or VB compiler (can't remember where this check is done off the top of my head) does not understand how to translate this to an equivalent bit of SQL. Hence it generates an error. You need to use a string comparison function which is supported by LINQ2SQL.
EDIT Update
It looks like the CompareString operator should be supported in the Linq2SQL case. Does subsonic have a different provider which does not support this translation?
http://msdn.microsoft.com/en-us/library/bb399342.aspx
The problem is with SubSonic3's SQL generator and the expression tree generated from VB.NET.
VB.NET generates a different expression tree as noted by JaredPar and SubSonic3 doesn't account for it - see Issue 66.
I have implemented the fix as described but it has yet to merge into the main branch of SubSonic3.
BlackMael's fix has been committed:
http://github.com/subsonic/SubSonic-3.0/commit/d25c8a730a9971656e6d3c3d17ce9ca393655f50
The fix solved my issue which was similar to John Granade's above.
Thanks to all involved.
This relates to the Dolphin variant of Smalltalk.
I'm digging around in the image to try and figure this out but haven't
find the correct method invocation yet and I'm hoping someone might be
able to help shortcut this process. What I'm trying to do is to find
all methods (either within the entire system or, preferably, just
within a single class) which refer to a given string, symbol, or
method. I've found the #references family of methods in
SmalltalkSystem but have not had luck figuring out how to get them to
give back something resembling what I want.
The programmatic way, here we go
SmalltalkSystem current browseContainingText: 'Dolphin'.
I don't have Dolphin at hand, but the following code should work in all Smalltalk with the refactoring engine (this includes Dolphin):
result := BrowserEnvironment new matches: 'Dolphin'.
Then you can iterate over the results like this:
result classesAndSelectorsDo: [ :class :selector | ... ].
VB.NET has a very handy "with" statement, but it also lets you use it on an unnamed variable, like this:
With New FancyClass()
.Level = "SuperSpiffy"
.Style = Slimming
.Execute()
End With
Is there a way to get at the "hidden" instance, so I can view its properties in the Immediate window? I doubt I'll get it in the watch windows, so immediate is fine.
If you try to access the instance the same way (say, when .Execute() throws an exception) from the Immediate window, you get an error:
? .Style
'With' contexts and statements are not valid in debug windows.
Is there any trick that can be used to get this, or do I have to convert the code to another style? If With functioned more like a Using statement, (e.g. "With v = New FancyClass()") this wouldn't pose a problem.
I know how With is working, what alternatives exist, what the compiler does, etc. I just want to know if this is possible.
As answered, the simple answer is "no".
But isn't another way to do it: instead of declaring and then cleaning up the variable is to use the "Using".
Using fc as new FancyClass()
With fc
.Level = "SuperSpiffy"
.Style = Slimming
.Execute()
End With
End Using
Then you can use fc in the immediate window and don't have to remember to write a
fc=nothing
line.
Just some more thoughts on it ;)
What's wrong with defining a variable on one line and using it in a with-statement on the next? I realise it keeps the variable alive longer but is that so appalling?
Dim x = new SomethingOrOther()
With x
.DoSomething()
End With
x = Nothing ' for the memory conscious
Two extra lines wont kill you =)
Edit: If you're just looking for a yes/no, I'd have to say: No.
I hope there really isn't a way to get at it, since the easy answer is "no", and I haven't found a way yet either. Either way, nothing said so far really has a rationale for being "no", just that no one has =) It's just one of those things you figure the vb debugger team would have put in, considering how classic "with" is =)
Anyway, I know all about usings and Idisposable, I know how to fix the code, as some would call it, but I might not always want to.
As for Using, I don't like implementing IDisposable on my classes just to gain a bit of sugar.
What we really need is a "With var = New FancyClass()", but that might just be confusing!
You're creating a variable either way - in the first case (your example) the compiler is creating an implicit variable that you aren't allowed to really get to, and the in the second case (another answer, by Oli) you'd be creating the variable explicitly.
If you create it explicitly you can use it in the immediate window, and you can explicitly destroy it when you're through with it (I'm one of the memory conscious, I guess!), instead of leaving those clean up details to the magic processes. I don't think there is any way to get at an implicit variable in the immediate window. (and I don't trust the magic processes, either. I never use multiple-dot notation or implicit variables for this reason)