I am doing
static bool isWorking
{
get { return _isWorking; }
set {
myform.treeView1.Enabled = !value;
_isWorking = value;
}
}
and stepping through the debugger shows it stops at the first set line.
After trying this line instead
set { myform.treeView1.Enabled = !(_isWorking = value); }
I see that isWorking is set but myform.treeView1.Enabled is not. Whats going on?
What do you mean by "the debugger shows it stops"? Is it possibly that myform is null, or myform.treeView1 is null?
I can't remember the exact evaluation order in this case, but it could explain the symptoms you're describing. Knowing why the debugger "stops" is crucial though. Another possibility is that you're trying to access the UI from a non-UI thread, which would prevent the assignment to Enabled from working properly.
Oh, and please don't use your second version - assignment as a side-effect is very, very rarely a good idea. The only idiomatic use I know is when looping with IO:
string line;
while ( (line = reader.ReadLine()) != null)
and I only consider that acceptable because it's reasonably common. In this case it really looks like you could mean "==" instead of "=".
Because (_isWorking = value) returns always true. If you would write:
myform.treeView1.Enabled = !(_isWorking == value);
It works like: if isWorking is equal to value then Disable treeView. But in you case - no
Related
I may be overlooking something, well obviously I am. I am using an uninitialized variable of type int (carRequired). I am utilizing this variable inside an IF statement (code below). However, I get a warning stating the variable is never used yet it is. Yes, I am aware of not being good practice to embed sql, however I am told to do it this way for now.
public bool UpdateDiscrepancyReport()
{
var errorStatus = false;
int carRequired ;
carRequired = cbxCarRequired.Checked == false ? 0 : 1;
var updateQuery = "my query string ";
dbf.OpenConnection(updateQuery);
bool updateStatus = dbf.OpenConnection(updateQuery);
if (updateStatus)
{
errorStatus = true;
}
else
{
MessageBox.Show(#"Error in updating DR" + tbxDRNumber.Text+#" ",#"Update Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return errorStatus;
}
The variable is never used. It is assigned to, but the variable is never used after that assignment; you don't do anything after assigning the result of the ternary operation to it. In fact, the variable isn't necessary at all, and neither is errorStatus (in the original code you posted), since you never do anything in the code that will change it's value after it is initialized.
The code you've posted (prior to your edit that added several more lines) is the exact equivalent of
public bool UpdateDiscrepancyReport()
{
dbf.OpenConnection(updateQuery);
return false;
}
The compiler is telling you that the variable declaration and assignment to carRequired is meaningless, because it does not affect anything in your code. Determining whether the checkbox is checked or not only has meaning if your code does something differently based on that information, and the use of carRequired as written does nothing based on the value assigned; therefore, the assignment (and variable declaration) are useless.
Question: Is there a significant performance hit when assigning a variable to itself?
Although the code can be easily changed to avoid assigning a variable to itself or to use flags to detect how something should be assigned .. I like the use of a null coalescing operator to make cleaner initialization code. Consider the following code:
public class MyObject
{
public string MyString { get; set; }
}
public class Worker
{
Dictionary<int, string> m_cache = new Dictionary<string, string>();
public void Assign(ref MyObject obj)
{
string tmp = null;
if (some condition)
{
//can't pass in MyObject.MyString to out param, so we need to use tmp
m_cache.TryGetValue("SomeKey", out tmp); //assumption: key is guaranteed to exist if condition is met
}
else
{
obj.MyString = MagicFinder(); //returns the string we are after
}
//finally, assign MyString property
obj.MyString = tmp ?? obj.MyString;
//is there a significant performance hit here that is worth changing
//it to the following?
if (!string.IsEmptyOrNull(tmp))
{
obj.MyString = tmp;
}
}
}
Your question seems to boil down to this section:
//finally, assign MyString property
obj.MyString = tmp ?? obj.MyString;
To:
//is there a significant performance hit here that is worth changing
//it to the following?
if (!string.IsNullOrEmpty(tmp))
{
obj.MyString = tmp;
}
Realize, however, that the two versions are not the same. In the first case (using the null coalescing operation), obj.MyString can get assigned to string.Empty. The second case prevents this explicitly, since it's checking against string.IsNullOrEmpty, which will precent the assignment in the case of a non-null, empty string.
Since the behavior is different, I would say this is not an optimization, but rather a behavioral change. Whether this is appropriate depends on the behavior this method is specified to demonstrate. How should empty strings be handled? That should be the determining factor here.
That being said, if you were to do an explicit null check, the performance would be near identical - I would suggest going for maintainability and readability here - to me, the first version is simpler, as it's short and clear.
Also, looking at your code, I think it would be far simpler to put the assignment into the statement. This would make the code far more maintainable (and more efficient, to the delight of your boss...):
public void Assign(ref MyObject obj)
{
if (some condition)
{
string tmp = null;
//can't pass in MyObject.MyString to out param, so we need to use tmp
m_cache.TryGetValue("SomeKey", out tmp); //assumption: key is guaranteed to exist if condition is met
obj.MyString = tmp;
}
else
{
obj.MyString = MagicFinder(); //returns the string we are after
}
}
Given the assumption in the code (that the key will always exist in cache if your condition is true), you can even simplify this down to:
public void Assign(MyObject obj) // No reason to pass by ref...
{
obj.MyString = someCondition ? m_cache["SomeKey"] : MagicFinder();
}
You shouldn't worry about that, the impact should be minimal. However, think about how many people are actually aware of the null coalescing operator. Personally, I find the latter more readable at a glance, you don't have to think about it what it means.
The performance worry of checking if a string is null or empty is of no immediate concern, but you could alter your code to be more concise, I think:
string tmp = null;
if (some condition)
{
m_cache.TryGetValue("SomeKey", out tmp);
}
if (string.IsNullOrEmpty(tmp))
{
tmp = MagicFinder();
}
obj.MyString = tmp;
"Premature optimization is the root of all evil."
In other words, I doubt that any theoretical answer will be representative of real world performance, unless you happen to know how it compiles down to bytecode... How about you create a quick and dirty test framework that'll run it 1000 times with random values (null or valid strings) and measure the performance yourself?
EDIT: To add, I'd be rather surprised if the performance was significantly different enough that it would matter in the grand scheme of things. Go for legibility first (although you could argue in favor of both :))
The code below looked ok to me when I wrote it, but when I came back to it again, it was pretty hard to grasp what is going on. There used to be parenthesis around value == ..., but I had to remove them after StyleCop became mandatory (I cannot really control this). So, how can I improve this section of code? I was thinking: x = value == y ? true : false;, but that probably is even more confusing, plus silly, although compiler will optimize that.
set
{
Debug.Assert(value == ConfigType.DATABASE || value == ConfigType.FILE,
"Configuration type must be either 'File-based' or 'Database-based'; it was: "
+ value.ToString());
// HG TODO: The following is concise but confusing.
this.fileBasedRadioButton.Checked = value == ConfigType.FILE;
this.databaseBasedRadioButton.Checked = value == ConfigType.DATABASE;
}
bool isFile = value == ConfigType.FILE;
bool isDatabase = value == ConfigType.DATABASE; // or isDatabase = !isFile
Debug.Assert(isFile || isDatabase,
"Configuration type must be either 'File-based' or 'Database-based'; it was: "
+ value.ToString());
this.fileBasedRadioButton.Checked = isFile;
this.databaseBasedRadioButton.Checked = isDatabase;
This makes it a little more readable (explicitly declaring the bool), you know it has to be true or false.
And this way, if you need to (maybe in the future) change settings based on file/database in the same method, you already have the bool handy, instead of checking each time
If you don't want to use the ?: operator use if..else. Sure it is a little more verbose, but you wont spend more than a few seconds figuring it out.
A few months from now when you revisit this code you will be glad you took an extra 5 lines.
Making code easy to maintain should be your #1 priority.
if (value == ConfigType.FILE)
this.fileBasedRadioButton.Checked = true;
else
this.fileBasedRadioButton.Checked = false;
if (value == ConfigType.DATABASE)
this.databaseBasedRadioButton.Checked = true;
else
this.databaseBasedRadioButton.Checked = false;
Indent the second and third line of the Debug.Assert() method. It should then look like this:
Debug.Assert(value == ConfigType.DATABASE || value == ConfigType.FILE,
"Configuration type must be either 'File-based' or 'Database-based'; it was: "
+ value.ToString());
I know this is really a minor stylistic alteration, but I've always found when I have to pass a lot of arguments or have some really long statement, when I carry over to a newline I should indent before the ;.
It prevents the Debug.Assert() from looking like 3 lines.
As for the value==, I agree with the previous poster. You should make a bool isDatabase and isFile to prevent calling a field from ConfigType twice in your first arg.
From the documentation:
A String containing the string value "true" to indicate that shadow copying is turned on; or "false" to indicate that shadow copying is turned off.
And its been this way since 1.1. Can anyone shed any light?
I reflector'd the getter and setter for good measure:
public string ShadowCopyFiles
{
get
{
return this.Value[8];
}
set
{
if ((value != null) && (string.Compare(value, "true", StringComparison.OrdinalIgnoreCase) == 0))
{
this.Value[8] = value;
}
else
{
this.Value[8] = null;
}
}
}
//The referenced Value property...
internal string[] Value
{
get
{
if (this._Entries == null)
{
this._Entries = new string[0x10];
}
return this._Entries;
}
}
private string[] _Entries;
So maybe the Value array begets an easier copy constructor or something?
Lack of caffeine. Some things are not meant to be understood.
This clearly seems to be a mistake from .NET first version, not fixed because that could break "legacy" code.
Gosh, I just found this:
Thanks for your feedback on the .NET Framework! We agree that this is an oversight and that the property type should be a boolean. However, it is quite difficult (if not impossible) to make this change in a backwards compatible release (such as Orcas), because we would break the code of any customer relying on string comparisons. So unfortunately we must weigh the risk of breaking compatibility vs. the benefits of API cleanliness...and when it comes to best supporting our customer base, the former typically wins. We will track this internally as a good thing to improve and we'll continue to consider it in future releases.
From here
Lets say I have an object with two boolean properties:
public bool AdvancedMode{ get; set; }
public bool DumpDiagnostics{ get; set; }
The domain rules state that DumpDiagnostics is not allowed unless AdvancedMode is also true. So throughout the code you might see statements like this:
if( options.AdvancedMode && options.DumpDiagnostics ){ ... }
The problem with this is that it's easy to forget to add the check forAdvancedMode and accidentally check only for DumpDiagnostics.
if( options.DumpDiagnostics ) // Oh no!
So there are two solutions that I can think of:
Option 1: DumpDiagnostics only returns true when AdvancedMode is true.
public bool DumpDiagnostics
{
get{ return AdvancedMode && _dumpDiagnostics; }
set{ _dumpDiagnostics = value; }
}
Option 2: New property that reflects the condition I'm looking for
public bool CanDumpDiagnostics{ get{ return AdvancedMode && DumpDiagnostics; } }
Question: Which is better?
Option #1 seems pretty easy and less prone to error. There's always one authority on whether diagnostics can be dumped. But, it does change the set -> get semantics where you can assign DumpDiagnostics = true, followed by if( DumpDiagnostics ) where it returns false.
Option #2 is good because it isolates the logic and makes it clear what the purpose is. The biggest drawback I see with it is that it's still easy to just check for DumpDiagnostics instead of using the new CanDumpDiagnostics property.
p.s. I know it's an awkward title but couldn't come up with something more precise, feel free to modify.
Alternately, pick option 3... turn the two booleans into an enum:
public enum Mode
{
Normal,
Advanced,
AdvancedWithDiagnostics
}
(with names that are more appropriate for what you are doing)
Addendum:
If you want to go really "advanced", you can even use the following:
public enum Mode
{
Normal = 0,
Advanced = 1,
AdvancedWithDiagnostics = 3
}
And use the following properties (again, pick better naming than mine!):
public Mode SelectedMode { get; set; }
public bool AdvancedMode { get { return (SelectedMode & 1) != 0; } }
public bool DumpDiagnostics { get { return (SelectedMode & 2) != 0; } }
Option 2 makes more sense to me. I don't like properties which can be set but don't "take hold". I was going to suggest throwing an exception in the setter, but then remembered that you'd also have to throw an exception in the setter for AdvancedMode in case that was reset to false.
I'd rename DumpDiagnostics to something like DiagnosticDumpRequested to make it clearer that it doesn't guarantee it'll be honoured.
What are the domain rules of the getting and setting the states? In other words, it seems to me like the "set" function for DumpDiagnostics should also set the AdvancedMode. If this is true, then just go with option 1 and you'll only need to check that DumpDiagnostics is set in the rest of your code.
Option 1 is misleading. DumpDiagnostics should not be equal to AdvancedMode && DumpDiagnostics. I would go with option 2