Can the C# var Keyword Be Misused?
Posted as an alternative to another member's tip, so it starts mid-conversation.
I agree that in the above example, the use of var is a bit excessive. However, for very long types (such as a dictionary with the key and value both being lists of some nested classes… see below code example), this might actually improve readability (seeing so many details may overwhelm you). Assuming the method and variable are named well, you should have a general idea of what is returned. And, you can mouse over the “GetData” method to see what the return type is.
I’d say var in the example you give would be useful for long types but not very useful for short types. However, it wouldn’t slow you down too much… if you really need to see what the type is, just mouse over the method.
// Readable, but must mouse over method to see type returned.
var x = GetPairs();
// Readable, but distracting.
Dictionary<List<Animal.Dog>, List<Animal.Cat>> y = GetPairs(); Changing a WinForms Control on the UI Thread from Another Thread
Posted as an alternative to another member's tip, so it starts mid-conversation.
This version works regardless of parameters:
public void AnyMethod(int parameter)
{
MethodInvoker wrapper = new MethodInvoker(delegate()
{
// Do your thing here!
});
if (this.InvokeRequired)
this.Invoke(wrapper);
else
wrapper();
}Note also that it does not need to be wrapped in a method to work. You can just place it inline. Any required variables will be captured by the delegate.
int parameter = 5;
MethodInvoker wrapper = new MethodInvoker(delegate()
{
// Do your thing here! For example:
lblCount.Text = parameter.ToString();
});
if (this.InvokeRequired)
this.Invoke(wrapper);
else
wrapper(); Multi-Line Lambdas in C# and VB.NET
Thanks to a recent answer on CodeProject, I discovered that lambdas can be made using multiple lines of code (I always assumed they could only use a single line of code). Here is how it’s done in C#:
Action<int, int> dialog = (int1, int2) =>
{
MessageBox.Show(int1.ToString());
MessageBox.Show(int2.ToString());
};
dialog(1, 2);The key there is to use curly braces to create a code block to contain multiple lines. After some Google searching, I found that this can be done in VB.NET as well:
Dim dialog As Action(Of Integer, Integer) =
Sub(int1, int2)
MessageBox.Show(int1.ToString())
MessageBox.Show(int2.ToString())
End Sub
dialog(1, 2)The key there is to add “End Sub” (or “End Function”) and place each statement on a new line.
Checking Whether a String Is a Palindrome
Posted as an alternative to another member's tip, so it starts mid-conversation.
I prefer this technique (uses less memory and may be faster, but requires slightly more code):
public bool IsPalindrome(string str, StringComparison comparisonType)
{
bool valid = true;
int halfway = str.Length / 2;
int lastIndex = str.Length - 1;
for (int i = 0; i < halfway; i++)
{
if (!str.Substring(i, 1).Equals(str.Substring(lastIndex - i, 1), comparisonType))
{
valid = false;
break;
}
}
return valid;
}You can then provide an overload to avoid passing in the comparison type:
public bool IsPalindrome(string str)
{
return IsPalindrome(str, StringComparison.OrdinalIgnoreCase);
} Call Functions Until One Meets Condition
Thanks to cechode for inspiring this tip/trick. Suppose you have the following functions:
bool Step1()
{
return true;
}
bool Step2(int val1, int val2)
{
return val1 == val2;
}
bool Step3()
{
MessageBox.Show("I will be reached.");
return false;
}
bool Step4()
{
throw new Exception("This should be impossible!");
}Function Step1() As Boolean
Return True
End Function
Function Step2(ByVal val1 As Integer, ByVal val2 As Integer) As Boolean
Return val1 = val2
End Function
Function Step3() As Boolean
MessageBox.Show("I will be reached.")
Return False
End Function
Function Step4() As Boolean
Throw New Exception("This should be impossible!")
End FunctionIf you want to execute each of those in sequence until one returns false, you can do the following:
new Func<bool>[]
{
Step1,
// You can use a lambda to wrap a function with a different signature.
() => Step2(1, 1),
Step3,
Step4,
// You can use a lambda to avoid the use of a function.
() => 0 == 1
}.Any((step) => !step());' This is achieved fairly easily in VB.NET
Select Case False
Case Step1()
Case Step2(1, 1)
Case Step3()
Case Step4()
Case 0 = 1
End SelectNote that the result need not be true or false; it can be any value or condition. I could, for example, process each function until the result is an integer greater than or equal to 5 (Note that in VB.NET the Select Case statement can’t handle conditions, it can only handle values, so the code is modified accordingly):
// This assumes each "Step" function from above returns an int rather than a bool.
new Func<int>[]
{
Step1,
() => Step2(1, 1),
Step3,
Step4,
() => 0 + 1
}.Any((step) => step() >= 5);' VB.NET.
Dim steps() As Func(Of Integer) =
{
AddressOf Step1,
Function() Step2(1, 1),
AddressOf Step3,
AddressOf Step4,
Function() 0 + 1
}
' We test against a condition rather than a value.
steps.Any(Function([step]) [step]() >= 5)The condition >= 5 is a very short one, so this won’t save you any typing over the short-circuiting technique shown below. However, it would save you some typing for longer conditions. Specifying the condition only once rather than for each value also reduces the probability that you will make a mistake when typing. And if you change the condition later on, you only have to change the condition in one place rather than many. Here is the short-circuiting approach, which leads to duplicated code:
// Don't do this.
if (Step1() >= 5 ||
Step2(1, 1) >= 5 ||
Step3() >= 5 ||
Step4() >= 5 ||
0 + 1 >= 5)
{ }' VB.NET. Don't do this.
If Step1() >= 5 OrElse
Step2(1, 1) >= 5 OrElse
Step3() >= 5 OrElse
Step4() >= 5 OrElse
0 + 1 >= 5 Then
End IfWhile shorter for this example (due to the short condition), this code also has the maintenance problems and higher probability of human error explained above.
Navigate a Silverlight WebBrowser to a URL with a Hash
If you try to set the Silverlight WebBrowser control to navigate to http://translate.google.com/#en|fr| either via the Source property in the XAML or by using the Navigate function, you will be presented with an exception (strangely, the Windows Forms WebBrowser has no problem with this URL). It seems the Uri class doesn’t like to construct URLs that contain a pipe character in the hash (aka, fragment identifier) of the URL (the part of the URL that comes after the ”#”). Here is the workaround:
string html = string.Format(
@"<html><body><script type='text/javascript'>window.location = '{0}';</script></body></html>",
"http://translate.google.com/#en|fr|");
myWebBrowser.NavigateToString(html);All you have to do is navigate to some HTML that has JavaScript that navigates to the URL you want the WebBrowser to visit. Here’s the VB.NET version:
Dim html As String = String.Format(
"<html><body><script type='text/javascript'>window.location = '{0}';</script></body></html>",
"http://translate.google.com/#en|fr|")
myWebBrowser.NavigateToString(html)I suspect this is either a .NET bug in the implementation of Uri or pipe characters may not strictly be allowed in fragment identifiers. Whatever the reason, this is the workaround (though if somebody else has a more elegant solution, I would love to see it).