How to make pass by reference method working - c#

I wrote a reference method in a class, and call it in public partial class DYBook : Form, but it is not working, the value doesn't change. If I put postCode.Text instead of temp, there will return an error. I don't know what was wrong here.
public static bool DYPostalCodeValidation(ref string inputField)
{
Regex pattern = new Regex(#"^([A-Za-z]\d[A-Za-z][\s]?\d[A-Za-z]\d)$");
if (inputField == "" || inputField == null)
{
return false;
}
else if (pattern.IsMatch(inputField))
{
inputField = inputField.ToUpper();
if (inputField.Length == 6)
{
inputField = inputField.Insert(3, " ");
}
return true;
}
else
{
return false;
}
}
call it here
Private string temp;
temp = postalCode.Text;
if (DYValidation.DYPostalCodeValidation(ref temp) == true)
{
postalCode.Text = temp;
}
else
{
postalCode.Focus();
errorMessage.Text += "Postal Code is invalid" + "\n";
}

Well, you can't pass directly postalCode.Text as a reference parameter. Instead, your pathway is correct.
To solve the problem, put a breakpoint where you check pattern.IsMatch(inputField). Make sure your input match with the regex. If these lines of codes doesn't run, you can't obtain what you want to.
else if (pattern.IsMatch(inputField))
{
inputField = inputField.ToUpper();
if (inputField.Length == 6)
{
inputField = inputField.Insert(3, " ");
}
return true;
}

postalCode.Text is a property which internally will be interpreted as method-call.
The ref keyword expects a reference to a variable and NOT to a method.

= will reassign a reference
You need to modify the string reference itself, not reassign it.
For example, an actual input field object would allow for
inputField.Text = inputField.Text.ToUpper();
This will preserve the input field reference, but update its inner Text property

Related

Initialize value in dictionary only once, then just update

I'm currently working to track packages when they move between bays, these changes happen every dozen or so seconds, so I have several threads accessing some dictionaries. The idea is that the first few times, I will not have the lastBay value (the program is just starting), but when A == B for the first time, I save the value of A (the bay that the pacakage has landed into, therefore the last bay at which it has been) and then just update said value every time A == B again.
private void in_bay()
{
String line_type = getDictionaryValues("global", "line_type").getStringValue();
bool result = false;
switch (line_type)
{
case "A_1":
int A = getVariableFromBucket("A_Act").getIntValue();
int B = getVariableFromBucket("A_Next").getIntValue();
result = A == B ? true : false;
if (result)
{
setDictionaryValues("global", "lastBay", new Variable("UNSIGNED8") { binaryValue = Utils.intToByteArray(A) });
}
break;
}
setVariableInBucket("IN_BAY", BitConverter.GetBytes(result));
log("IN_BAY flag in BUCKET: " + getVariableFromBucket("IN_BAY").getBoolValue(), DEBUG);
if (getDictionaryValues("global", "lastBay").binaryValue != null)
{
log("lastBay value in global: " + getDictionaryValues("global", "lastBay").getIntValue(), DEBUG);
}
else
{
log("undefined bay",DEBUG);
}
}
I have a getDictionaryValue() function that returns the variables (or an empty one if it's not in the dictionary):
public Variable getDictionaryValues(String DictionaryName, String VarName)
{
try
{
return functionDictionary[DictionaryName][VarName];
}
catch (Exception)
{
Variable emptyVariable = new Variable()
{
additionalInfo = null,
arrivalTime = 0,
binaryValue = null,
numBits = 0,
signed = false,
varType = null
};
return emptyVariable;
}
}
and a setDictionaryValue() function that actually sets the values to the dictionary selected:
public void setDictionaryValues(String DictionaryName, String VariableName, Variable VaValue)
{
try
{
lock (GlobalConstants.filtersLock)
{
if (!functionDictionary.ContainsKey(DictionaryName))
{
functionDictionary.Add(DictionaryName, new Dictionary<String, Variable>());
}
if (!functionDictionary[DictionaryName].ContainsKey(VariableName))
{
functionDictionary[DictionaryName].Add(VariableName, Value);
}
else
{
functionDictionary[DictionaryName][VariableName] = Value;
}
}
}
catch (Exception e)
{
log("An error has ocurred when setting values to functionDictionary: "+ e,DEBUG);
throw new Exception(e.ToString());
}
}
The problem is that the first time A == B It logs correctly the values being received, but when the values change again (the package starts moving again) the code no longer displays the values of lastBay, as if the dictionary global no longer has a value for lastBay. I attach an image with a reference as to the expected results and the results obtained:
What am I missing here?
From the comment thread, it looks like the problem is that in_bay is being called on different object instances, and functionDictionary is a non-static field, so you're dealing with different dictionary instances each time.
I just want to take the opportunity to point out how much simpler your code could be if you just used classes and variables rather than adding dictionaries and "Variable" objects as a layer of abstraction.
private void in_bay()
{
string? line_type = BayState.line_type;
bool result = false;
if(line_type == "A_1")
{
int A = Bucket.A_Act;
int B = Bucket.A_Next;
result = A == B;
if (result)
{
BayState.lastBay = A;
}
}
Bucket.IN_BAY = result;
log("IN_BAY flag in BUCKET: " + Bucket.IN_BAY, DEBUG);
if (BayState.lastBay != null)
{
log("lastBay value in global: " + BayState.lastBay.Value, DEBUG);
}
else
{
log("undefined bay", DEBUG);
}
}
I can pretty much guarantee whatever "business need" is driving the desire for dictionaries and such can be accomplished in another way that still allows you to write clean and less error-prone code.

getting a registry key and value in C#

Sorry if this is simple, I haven't coded since college. I'm trying to write a program to view registry entries in Windows 7. I want to check to see if the registry value exists first, then check to see what the value is. If it doesn't exist, I want one message, if it does exist, I want one message reflecting a value of 1, and another reflecting a value of 0. I got the code to work if the registry key doesn't exist, but if I add the key and value it crashes. Not sure what I'm doing wrong here. Any suggestions would be appreciated. Here is my code.
using (RegistryKey Key = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\services\LanmanServer\Parameters"))
if (Key != null)
{
string val = (string)Key.GetValue("EnableOplocks");
if (val == null)
{
oplockTextBox.Text = "Not Present In Registry";
oplockTextBox.BackColor = Color.Yellow;
}
else if (val == "1")
{
opslockTextBox.Text = "NO";
opslockTextBox.BackColor = Color.Red;
}
else
{
oplockTextBox.Text = "YES";
oplockTextBox.BackColor = Color.Green;
}
}
else
{
MessageBox.Show("");
}
As far as I can tell, the EnableOplocks value for that registry key is a DWORD value, which will give you an int when you use GetValue() to retrieve it. Trying to cast an int to a string will produce an InvalidCastException.
Instead, you should try this:
int? val = Key.GetValue("EnableOplocks") as int?;
if (val == null)
{
// ..
}
else if (val == 1)
{
// ...
}
Or this:
object val = Key.GetValue("EnableOplocks");
if (val == null)
{
// ...
}
else
{
string strVal = val.ToString();
if (strVal == "1")
{
// ...
}
}
In general, please remember to provide all of the error information you have. Saying "it crashes" is not very informative.
The registry can hold data-types other than string. What is happening is you are likely getting a int returned and that is why you are crashing when you attempt to cast a int to a string
Get the value back and store it in a object and have your debugger break. You should then be able to see what datatype is stored in the object and change your code to make the correct cast.
The other option would be use .ToString() instead of casting, you would need to compare the string 1 (like you are now) instead of the value 1. However, I always prefer to just use the correct type instead of turning everything in to strings.
Use follow;
string val = Key.GetValue("EnableOplocks").ToString();
EDIT
using (RegistryKey Key = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\services\LanmanServer\Parameters"))
if (Key != null)
{
var val = Key.GetValue("EnableOplocks");
if (val == null)
{
oplockTextBox.Text = "Not Present In Registry";
oplockTextBox.BackColor = Color.Yellow;
}
else if (val.ToString() == "1")
{
opslockTextBox.Text = "NO";
opslockTextBox.BackColor = Color.Red;
}
else
{
oplockTextBox.Text = "YES";
oplockTextBox.BackColor = Color.Green;
}
}
else
{
MessageBox.Show("");
}

C# prompting for a boolean value

My searches have come up blank, or I am just not understand the results that I am finding. I am trying to prompt the user to input a boolean value, but I want the answer to be yes or no. Let me know if you need to see more code but I have this for the prompt.
public static bool getBoolInputValue(string inputType)
{
bool valid = false;
bool value = true;
string inputString = string.Empty;
do
{
inputString = GetInput(inputType);
if (!(String.IsNullOrEmpty(inputString)))
{
valid = bool.TryParse(inputString, out value);
}
if (!valid)
Console.WriteLine("Invalid " + inputType + " try again!");
} while (!valid);
return value;
}
This is the paramater for my boolean. Maybe this needs to be more specific?
public bool Nitrus
{
set { nitrus = value; }
get { return nitrus; }
}
Thank you for the help. I am fairly new to programming but cannot figure this out. It does prompt successfully, but it does not matter what answer I put into the box, it tells me it is not the right format.
If I understand correctly you want the user to type in "yes" and that will mean you have a True value. If that is correct, skip all the string.IsNullOrEmpty and bool.TryParse stuff and do something more like this.
//make it ToLower so that it will still match if the user inputs "yEs"
inputString = GetInput(inputType);
if (inputString.ToLower() == "yes")
{
value = true;
}
else
{
value = false;
}
//note that the if/else code is the same as directly applying
// the value from the comparison itself:
// value = inputString.ToLower() == "yes";
// this allows the user to type in "yes" or "y":
// value = inputString.ToLower() == "yes" || inputString.ToLower() == "y";
Boolean.TryParse only recognizes "True" and "False". For "Yes" and "No` or "On" and "Off", you need to write your own function.
public static bool getBoolInputValue()
{
bool value;
bool valid;
do
{
Console.WriteLine("Enter yes or no: ");
var inputString = Console.ReadLine();
if (String.IsNullOrEmpty(inputString))
{
continue;
}
if ( string.Equals(inputString, "yes")
{
value = true;
valid = true;
}
else if ( string.Equals(inputString, "no")
{
value = false;
valid = true;
}
} while (!valid);
return value;
}
Your program will only accept 'true' or 'false' as valid boolean values. If you want 'yes' or 'no', then you will need to do a string comparison.
valid = string.Compare(inputString, "yes", true) == 0 || string.Compare(inputString, "no", true) == 0;
...
value = string.Compare(inputString, "yes", true) == 0;

Error when assigning a boolean value

I am getting an error while assigning a value.
My code is:
protected bool ValidateProfile()
{
bool blnFirstName = false;
bool blnLastName = false;
bool blnEMail = false;
//(error on line below: "The left-hand side of an assignment must be a variable, property or indexer")
ValidateProfile() = false;
if txtFName != ""
blnFName = true;
if txtLName != ""
blnLName = true;
if txtEMail != ""
blnEMail = true;
if (blnFName) && (blnLName) && (blnEMail))
ValidateProfile = true;
}
How do I assign a boolean value to ValidateProfile ?
Thanks
You want
return false;
In C#, we don't assign values to the function name in order to return a value.
If you want to set the return value at a different point in time from when you return from the method, then you should do something like this:
bool retVal; // Defaults to false
if (condition)
retVal = true;
if (otherCondition)
retVal = false;
if (thirdCondition)
retVal = true;
return retVal;
You can't assign a value to a function. You need return false;
As others have pointed out, in C# you use return instead of MyFunction = x. In this scenario, you can assign the result of your final check to a boolean and return it:
bool retVal = (blnFName) && (blnLName) && (blnEMail);
return retVal;
Alternatively, you could just skip the assignment altogether:
return (blnFName) && (blnLName) && (blnEMail);
EDIT: I noticed you are using hungarian notation, which implies that txtFName is a TextBox. Keep in mind that C# doesn't have default properties like VB. If it is a TextBox, it will never equal "", because it's not of type System.String. I'm guessing you actually wanting to evaluate txtFName.Text
Change that last line to:
return false;
Although it seems you're always returning false here. Is there an option to return true?
Just a side note besides all the returns...
You may want to change this:
if txtFName != ""
To check if the String.IsEmptyOrNull(txtFName.Text)
Or at least initialize your variables to either null or String.Empty.
Just an FYI though.
You want to return false
Alright, taking the code you posted:
protected bool ValidateProfile()
{
return !String.IsNullOrEmpty(txtFName) && !String.IsNullOrEmpty(txtLName) && !String.IsNullOrEmpty(txtEMail);
}
Or
protected bool ValidateProfile()
{
bool returnValue = true;
if(String.IsNullOrEmpty(txtFName))
{
returnValue=false;
}
else if(String.IsNullOrEmpty(txtLName))
{
returnValue = false;
}
else if(String.IsNullOrEmpty(txtEMail))
{
returnValue = false;
}
return returnValue;
}
Though you could just return false as soon as you find an invalid field.
Not a C# programmer, but can't you just write:
return (txtFName != "") && (txtLName != "") && (txtEMail != "");
for the body of the function?

Asp.Net : Extended range validation

I'm using Asp.Net 2.0. I have a scenario where i need to check a user input against any of two ranges. For e.g. I need to check a textbox value against ranges 100-200 or 500-600. I know that i can hook up 2 Asp.Net RangeValidators to the TextBox, but that will try to validate the input against both the ranges, an AND condition,if you will. CustomValidator is an option, but how would I pass the 2 ranges values from the server-side. Is it possible to extend the RangeValidator to solve this particular problem?
[Update]
Sorry I didn't mention this, the problem for me is that range can vary. And also the different controls in the page will have different ranges based on some condition. I know i can hold these values in some js variable or hidden input element, but it won't look very elegant.
A CustomValidator should work. I'm not sure what you mean by "pass the 2 ranges values from the server-side". You could validate it on the server-side using a validation method like this:
void ValidateRange(object sender, ServerValidateEventArgs e)
{
int input;
bool parseOk = int.TryParse(e.Value, out input);
e.IsValid = parseOk &&
((input >= 100 || input <= 200) ||
(input >= 500 || input <= 600));
}
You will then need to set the OnServerValidate property of your CustomValidator to "ValidateRange", or whatever you happen to call it.
Is this the sort of thing you're after?
I do not believe this is possible using the standard RangeValidator control.
I did some searching and I believe your best solution is going to be to create your own CustomValidator control which you can include in your project to handle this scenario.
http://www.dotnetjunkies.ddj.com/Article/592CE980-FB7E-4DF7-9AC1-FDD572776680.dcik
You shouldn't have to compile it just to use it in your project, as long as you reference it properly.
You can use the RegularExpressionValidator with the ValidationExpression property set to
Edit: (whoops, 650 and 201 etc. were valid with the old pattern)
^(1\d{2}|200|5\d{2}|600)$
This will test the entered text for 100-200 and 500-600.
I extended the BaseValidator to achieve this. Its fairly simple once you understand how Validators work. I've included a crude version of code to demonstrate how it can be done. Mind you it's tailored to my problem(like int's should always be > 0) but you can easily extend it.
public class RangeValidatorEx : BaseValidator
{
protected override void AddAttributesToRender(System.Web.UI.HtmlTextWriter writer)
{
base.AddAttributesToRender(writer);
if (base.RenderUplevel)
{
string clientId = this.ClientID;
// The attribute evaluation funciton holds the name of client-side js function.
Page.ClientScript.RegisterExpandoAttribute(clientId, "evaluationfunction", "RangeValidatorEx");
Page.ClientScript.RegisterExpandoAttribute(clientId, "Range1High", this.Range1High.ToString());
Page.ClientScript.RegisterExpandoAttribute(clientId, "Range2High", this.Range2High.ToString());
Page.ClientScript.RegisterExpandoAttribute(clientId, "Range1Low", this.Range1Low.ToString());
Page.ClientScript.RegisterExpandoAttribute(clientId, "Range2Low", this.Range2Low.ToString());
}
}
// Will be invoked to validate the parameters
protected override bool ControlPropertiesValid()
{
if ((Range1High <= 0) || (this.Range1Low <= 0) || (this.Range2High <= 0) || (this.Range2Low <= 0))
throw new HttpException("The range values cannot be less than zero");
return base.ControlPropertiesValid();
}
// used to validation on server-side
protected override bool EvaluateIsValid()
{
int code;
if (!Int32.TryParse(base.GetControlValidationValue(ControlToValidate), out code))
return false;
if ((code < this.Range1High && code > this.Range1Low) || (code < this.Range2High && code > this.Range2Low))
return true;
else
return false;
}
// inject the client-side script to page
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
if (base.RenderUplevel)
{
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "RangeValidatorEx", RangeValidatorExJs(),true);
}
}
string RangeValidatorExJs()
{
string js;
// the validator will be rendered as a SPAN tag on the client-side and it will passed to the validation function.
js = "function RangeValidatorEx(val){ "
+ " var code=document.getElementById(val.controltovalidate).value; "
+ " if ((code < rangeValidatorCtrl.Range1High && code > rangeValidatorCtrl.Range1Low ) || (code < rangeValidatorCtrl.Range2High && code > rangeValidatorCtrl.Range2Low)) return true; else return false;}";
return js;
}
public int Range1Low
{
get {
object obj2 = this.ViewState["Range1Low"];
if (obj2 != null)
return System.Convert.ToInt32(obj2);
return 0;
}
set { this.ViewState["Range1Low"] = value; }
}
public int Range1High
{
get
{
object obj2 = this.ViewState["Range1High"];
if (obj2 != null)
return System.Convert.ToInt32(obj2);
return 0;
}
set { this.ViewState["Range1High"] = value; }
}
public int Range2Low
{
get
{
object obj2 = this.ViewState["Range2Low"];
if (obj2 != null)
return System.Convert.ToInt32(obj2);
return 0;
}
set { this.ViewState["Range2Low"] = value; }
}
public int Range2High
{
get
{
object obj2 = this.ViewState["Range2High"];
if (obj2 != null)
return System.Convert.ToInt32(obj2);
return 0;
}
set { this.ViewState["Range2High"] = value; }
}
}

Categories

Resources