I have a method that returns an ItemCollection, I want to stop the function early if there is no information provided. I would normally do this with a return; however as my method expects an ItemCollection it fails. I have this as a work around but it seems frankly hacky. Is there something I am missing. I tried just return; and I would prefer not throw an exception.
private ItemCollection loadLeft_Click(object sender, RoutedEventArgs e)
{
var leftUser = UsrLeft.Text;
if (leftUser == "")
{
MessageBox.Show("No User Entered");
GroupListLeft.Items.Add("");
var fail = GroupListLeft.Items;
return fail;
}
//Succesful test do stuff
var leftItems = GroupListLeft.Items;
return leftItems;
}
You have few options:
throw a new Exception (maybe even a custom one like NoUserEnteredException("someText")).
return null
return an empty collection or dummy object (see Null-object pattern)
The last one is better choice, in this case you don't need write a null-check or a try-catch section in client code.
You will need to return something that equates to an ItemCollection, depending on how you may want the calling procedures to handle such a return you could use a null return:
if (leftUser == "")
{
MessageBox.Show("No User Entered");
return null;
}
Or return a new ItemCollection e.g.
if (leftUser == "")
{
MessageBox.Show("No User Entered");
return new ItemCollection();
}
You will need to return null, like
private ItemCollection loadLeft_Click(object sender, RoutedEventArgs e)
{
var leftUser = UsrLeft.Text;
if (leftUser == "")
{
MessageBox.Show("No User Entered");
return null;
}
//Succesful test do stuff
var leftItems = GroupListLeft.Items;
return leftItems;
}
You can use "return null" which I do from time to time, but its not a good coding convention. Another option is to throw an exception and then catch it. Both is bad coding conventions and makes the code that uses this button add some rather obscure logic and dependencies.
From studying SOLID principles I would argue a better solution is to make a new type of object to return. f.ex. one that holds a list, but also a status message and then make it react a bit like when you have an HTTP request that depends on a success and otherwise cannot expect to have any content. This way, the object makes it clearer what to expect.
A fourth option, since this sounds UI related, is to possible have the click callback somehow and either update the collection, or update with an error message directly. But this might also be a bad coding convention that has impractical dependencies in the code.
Your code seems to return an object when you click on something.
(I am no expert in WPF, i don't know if this is possible).
I would encapsulate the function that returns the ItemCollection in a separate function and check whether the User is valid BEFORE calling this function.
This way you ensure that the ItemCollection is always valid (because you don't even try to retrieve it with an invalid user). Something like this:
private void loadLeft_Click(object sender, RoutedEventArgs e) {
var leftUser = UsrLeft.Text;
if(leftUser != "") {
ItemCollection coll = getItemCollectionForUser(leftUser);
}else {
//Error Handling
}
}
private ItemCollection getItemCollectionForUser(string user) {
//return ItemCollection here
}
Note how I wrote a separate function that returns the ItemCollection and the Click function returns nothing.
Related
I have the following function:
public void Test(string testString)
{
//Do Stuff
}
At some points in my code, I have to repeatedly check if the parameter is empty string/null/whitespace to skip the body method. The usual ways I've done this till now, are the following:
public void Test(string testString)
{
if(!string.IsNullOrWhiteSpace(testString))
{
//Do Stuff only if string has text in it.
}
}
Or
public void Test(string testString)
{
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
Is there a way to create a custom attribute that checks if the parameter of the function is empty etc, to skip the method? I've had some experiece (basic stuff), with custom attributes, but I can't figure out a way to make the attribute skip the method body.
The ideal end product of the implementation would be the following:
[SkipIfEmptyParameter]
public void Test(string testString)
{
//Do Stuff only if string has text in it.
}
Of course, any suggestion is welcome that helps minimize the recurring code if the attribute implementation is not possible.
Edit: Example of the problem I want to solve.
I have the following methods. I get from Microsoft Test Manager, some parameters that our test scenario are expecting (what the values should be). There is a SharedStep implementation that asserts the user's info:
public void AssertUser(UserDTO expectedUserInfo)
{
VerifyUserName(expectedUserInfo.name);
VerifyUserSurname(expectedUserInfo.surname);
VerifyUserAge(expectedUserInfo.age);
VerifyUserHeight(expectedUserInfo.height);
}
private void VerifyUserName(string name)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's name at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
private void VerifyUserSurname(string surname)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's surname at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
private void VerifyUserAge(string age)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's age at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
private void VerifyUserHeight(string height)
{
//If the string parameter is empty, means the MTM scenario does not
//want to validate the user's height at this point, so skip the
//verification below.
if(string.IsNullOrWhiteSpace(testString)) { return; }
//Do Stuff only if string has text in it.
}
The "Do Stuff" contain Selenium implementation that handle WebElements and might be time consuming, so if we don't want to validate that specific value, we just skip the whole method.
Now, when creating the scenarios over to Microsoft Test Manager, the shared steps allows the tester to decide what elements of the page will be validated. If some of the parameters are empty, then the code just skips the blocks and goes to w/e validation the user wants (still, the implementation is for every info the user has, but we just assign value to each parameter we want to test, and every parameter that does not have a value, just gets it's method body skipped).
The problem is, if I want to change the condition of skipping the method, I will have to go to each method and manually change the IF statement. Hence why I though it might be a good idea to have an attribute for every method that validates information.
P.S. I'm talking about hundreds of methods that have the IF implementation at the start.
The only way that I know that this can be done using attributes is aspect oriented programming using a product like post sharp and method interception. Alternatively if the methods are defined in an interface this can also be done by using RealProxy but seems more than a little overkill.
The way you are doing it is actually pretty good. But as Evk pointed out in the comments: You should extract the "skip checking" into a separate method, especially if the check is always the same and needs to be changed globally. Using an attribute would solve the problem, but is a little complicated to use.
Instead, take a look at the code below. Looks pretty clear, doesn't it? Don't use too many comments (and don't copy-paste them into every method, that is of no use). This way, you have the same benefits as if you would use a custom attribute but without the ugliness of using reflection.
public void AssertUser(UserDTO expectedUserInfo)
{
VerifyUserName(expectedUserInfo.name);
VerifyUserSurname(expectedUserInfo.surname);
VerifyUserAge(expectedUserInfo.age);
VerifyUserHeight(expectedUserInfo.height);
}
private void VerifyUserName(string name)
{
if (ShouldSkipValidation(name)) return;
// code here...
}
private void VerifyUserSurname(string surname)
{
if (ShouldSkipValidation(surname)) return;
// code here...
}
private void VerifyUserAge(string age)
{
if (ShouldSkipValidation(age)) return;
// code here...
}
private void VerifyUserHeight(string height)
{
if (ShouldSkipValidation(height)) return;
// code here...
}
// The MTM scenario does not want to validate values that satisfy the check below
private bool ShouldSkipValidation(string value)
{
return string.IsNullOrWhiteSpace(value) || value == "<>";
}
I don't think attributes make it possible to achieve what you are trying to achieve.
But you can use a custom method invoker instead:
static void Main(string[] args)
{
InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), null);
InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), "");
InvokeIfNotNullOrWhitespace((inputStr) => TestMethod(inputStr), "abc");
// RESULT:
// Trying to invoke action...
// Trying to invoke action...
// Trying to invoke action...
// I have been invoked!
}
static void InvokeIfNotNullOrWhitespace(Action<string> action, string inputString)
{
Console.WriteLine("Trying to invoke action...");
if(!string.IsNullOrWhiteSpace(inputString))
action.DynamicInvoke(inputString);
}
static void TestMethod(string input)
{
Console.WriteLine("I have been invoked!");
}
The reason why I think attributes won't work is because they can't control what is going on inside the method. Instead, "other external things" can look at those attributes and decide what to do.
To achieve what you are trying to achieve, an "external thing" would need to look at the attribute and decide if it is executed or not. This would be equivalent to what I wrote: an external invoker that unifies the "check string validity" procedure.
Here are my 4 cents on this,
Calling an attribute involves reflection, already a bad idea as
you need to find out if the attribute is set;
You're avoiding a "1 liner" in your code that actually is quite
easy to type;
Use method overloading;
You can use Aspect oriented programming that will basically inject the below samples in your code at compile time. You can control the way this works with annotations and would not have a negative effect on the generated runtime.
Here are some variations:
//1
if(string.IsNullOrEmpty(testString))
return;
//2
if(string.IsNullOrEmpty(testString) ||string.IsNullOrWhiteSpace(testString) )
return;
When going for 3 just make sure you do not mix returning null, or boolean true/false based on the "missing" text. Only you know how your code should flow.
Perhaps you are looking for method overloading
you can do that by creating 2 methods with the same name in the same class.
You can call the empty MyMethod() from the MyMethod(with string) so you do not duplicate the logic.
return string.IsNullOrEmpty(testString)?MyMethod():MyMethod(testString);
I just need to create a function to checkbox that will return the current value of checkbox.
I wrote :
private void Checkbox_check()
{
if (checkBox1.InvokeRequired)
return (int)checkBox1.Invoke(new Func<int>(checked));
else
return checkBox1.Checked; // bad here i know
}
What is bad here, can someone just write correctly this function? I need Invoke because can't use in another Thread without invoke. I just search a forum and web about help but can't find solution anywhere.
Don't use Func<> as it doesn't return anything. Use Action instead.
private void Checkbox_check()
{
if (checkBox1.InvokeRequired)
checkBox1.Invoke(new Action(Checkbox_check));
else
{
// do what you like to do on the ui context
// checkBox1.Checked; // bad here i know, yep...
}
}
Getting the checked state from another thread, you could do like this:
private bool Checkbox_check()
{
// result value.
bool result = false;
// define a function which assigns the checkbox checked state to the result
var checkCheckBox = new Action(() => result = checkBox1.Checked);
// check if it should be invoked.
if (checkBox1.InvokeRequired)
checkBox1.Invoke(checkCheckBox);
else
checkCheckBox();
// return the result.
return result;
}
I would not advise this, this could lead to deadlocks etc. I advise you to pass the checked value on the threadstart, so you don't have to do any crossthread calls.
You should write it this way:
private void Checkbox_check()
{
if (checkBox1.Invoke:DRequired)
return (int)checkBox1.Invoke(new Func<int>(checked));
else
return checkBox1.Checked.(initInvoke);
}
Relatively new to C#/.NET/GUI programming, but here goes. Right now I'm writing a business application at work using WinForms. I have about 5 textboxes and 1 combobox that I want to verify if is empty and if so then tell the user and set focus on that control. How should I go about doing this?
I could either have an if statement that checks each control:
if (usernameField IsNullOrEmpty) then:
setFocus(UsernameField);
return;
if (addressField IsNullOrEmpty) then:
setFocus(addressField);
return;
continue with rest of application as normal...
Or I could do this with exceptions:
try {
if (usernameField IsNullOrEmpty) then:
throw new Exception(usernameField);
if (addressField IsNullOrEmpty) then:
throw new Exception(addressField);
} catch (Exception e) {
setFocus(ControlField) // encapsulate in exception some way?
}
Or to prevent code duplication, just write a function:
try {
checkField(usernameField);
checkField(addressField);
} catch (Exception e) {
setFocus(ControlField) // encapsulate in exception some way?
}
void checkField(control ctrl) {
if (ctrl IsEmptyOrNull)
throw new Exception(ctrl);
}
Being relatively new to GUI programming, does a text field being empty deserve an exception or would this be considered normal program flow?
Throwing Exceptions for program flow is not recommended.
Write a helper method.
private bool IsTextboxValid(Textbox ctrl)
{
if(string.IsNullOrEmpty(ctrl.Text))
{
ctrl.Focus();
return false;
}
return true;
}
And to use it:
if(!IsTextboxValid(addressBox)) return;
if(!IsTextboxValid(nameBox)) return;
I would not use an exception, exceptions should be thrown in exceptional situations, user not filling in a field doesn't count. As for actually detecting the empty control and setting focus, there are tons of ways, like simple if checks as you have, to more complicated solutions with binding and validation and all that.
Answer: it was in the else code, but I thought there is no reason that code wouldn't point to that line.
Can someone offer an idea how it could be possible that I get "Object reference not set to an instance of an object" on this at Invoke method:
delegate void t(tabdescriptor tab);
internal void AddItem(tabdesciptor tab)
{
if (InvokeRequired)
{
t inv = new t(AddItem);
if (inv != null && tab!= null)
Invoke(inv, tab);
}
else
{
....
}
}
I'm not exactly sure what the actual issue is considering your example cannot be the code that executes, but please try something like this:
internal void AddItem(tabdesciptor tab)
{
if (InvokeRequired)
{
Invoke(new Action<tabdescriptor>(AddItem), tab);
}
else
{
//...
}
}
Also please make sure that it's not actually whatever is in the else part that fails.
If I remember correctly, this exception could be coming from inside the invoked method. If you place a try/catch inside the else of the AddItem method and a breakpoint inside the catch, do you catch the exception?
internal void AddItem(tabdesciptor tab)
{
if (InvokeRequired)
{
t inv = new t(AddItem);
if (inv != null && tab!= null)
Invoke(inv, tab);
}
else
{
try
{
....
}
catch
{
// breakpoint here
}
}
}
It's unclear whether it's a mistake in the given example, or not, but tab is never checked for null, yet it is passed as the argument.
Either it's probably null, or:
Also, inv is checked for null right after creating it (Good in C/C++, but unnecessary in C# as it throws an OutOfMemoryException upon failure), but it is done before checking o for null.
I am writing the following get and set for validating an input from a Text Box. Basically it is supposed to check if the user has entered all of the values.
When I leave the TextBoxes empty , it does nothing and shows a '0' in output where that variable was being used. It does however show the system generated exception and stops the execution, but I wonder why doesn't it validate the input through the properties?
Here is my code:
public double RecoDoseSize
{
get
{
return recoDoseSize;
}
set
{
if (!(value>0))
{
MessageBox.Show("Please Enter the recommended dose size for this product");
textBox8.Focus();
}
recoDoseSize = value;
}
}
private void Submit2_Click(object sender, RoutedEventArgs e)
{
TotalContentProduct = double.Parse(textBox7.Text);
recoDoseSize = double.Parse(textBox8.Text);
NoOfDosespUnit = TotalContentProduct/recoDoseSize;
}
You are setting recoDoseSize, the backing field, not RecoDoseSize, the property which has your code in it. Thus, your code isn't executed. You need to change the second line of your method body to
RecoDoseSize = double.Parse(textBox8.Text);
(note the capital R).
Other have given the correct answer to the question as stated. Namely that you should call the uppercased RecoDoseSize if you want to use the getter/setter.
However it is extremely bad practice to show a message box inside the setter, because it violates the Principle of Least Surprise.
When someone looks at the line RecoDoseSize = double.Parse(textBox8.Text); it is not at all obvious that this operation could cause a message box to appear.
There are occasionally exceptions where it does make sense to have a setter trigger UI changes (for instance the Visible property on controls) however the default should always be to not do this unless you are sure it will be more confusing to not do so (for instance it would be surprising if you set Visible = false however it was still visible).
Regarding your comment on how you should implement it, the checking should be done in the click handler and the property can just be an auto-property, like so:
public double RecoDoseSize { get; set; }
private void Submit2_Click(object sender, RoutedEventArgs e)
{
TotalContentProduct = double.Parse(textBox7.Text);
double enteredSize;
if (!double.TryParse(textBox8.Text, out enteredSize) || enteredSize <= 0)
{
MessageBox.Show("Please Enter the recommended dose size for this product");
textBox8.Focus();
return;
}
RecoDoseSize = enteredSize;
NoOfDosespUnit = TotalContentProduct / recoDoseSize;
}
You'll want to use TryParse because with Parse you'll get an error if the text isn't a valid double. What TryParse does is return true or false depending on whether it succeeded, and it populates the out parameter with the result if it's successful.
So what this does is if it either failed to parse the result, or the result is <= 0 it shows the message box. In that case it also returns from the method so the rest of it isn't executed. Alternatively the rest of the method could be in an else block in which case the return isn't needed. It's a matter a style which way is preferred.
You're never actually using the getter/setter. You are using the actual field name: recoDoseSize directly. Change it to RecoDoseSize.
private void Submit2_Click(object sender, RoutedEventArgs e)
{
TotalContentProduct = double.Parse(textBox7.Text);
RecoDoseSize= double.Parse(textBox8.Text);
NoOfDosespUnit = TotalContentProduct/recoDoseSize;
}
You shouldn't be handling focus in your set statement.
Also, you need to make sure that value is not null, otherwise you can't compare it to anything (greater-than, etc.).