Is there a better way to do this.
FileInfo f = new FileInfo("C://notebook.txt");`
public bool Archived
{
get
{
return (((File.GetAttributes(f.FullName))
& FileAttributes.Archive) == FileAttributes.Archive);
}
set
{
if (value == true)
{
if (!this.Archived)
{
File.SetAttributes(f.FullName,
File.GetAttributes(f.FullName) | FileAttributes.Archive);
}
}
else if (value == false)
{
if (this.Archived)
{
File.SetAttributes(f.FullName,
File.GetAttributes(f.FullName)
& ~FileAttributes.Archive);
}
}
}
}
`
Yes, as you have a FileInfo object you can use it's Attributes property instead of using the File.GetAttributes and File.SetAttributes methods:
public bool Archived {
get {
return (f.Attributes & FileAttributes.Archive) != 0;
}
set {
if (value) {
if (!this.Archived) {
f.Attributes |= FileAttributes.Archive;
}
} else {
if (this.Archived) {
f.Attributes &= ~FileAttributes.Archive;
}
}
}
}
Well, you can always start by simplifying the way you handle the value in the setter. Then you could avoid a double-get by reading the attributes at the top of the setter.
public bool Archived
{
get
{
return (((File.GetAttributes(f.FullName)) & FileAttributes.Archive) != 0);
}
set
{
var attributes = File.GetAttributes(f.FullName);
bool archived = ((attributes & FileAttributes.Archive) != 0);
if (value)
{
if (!archived)
File.SetAttributes(f.FullName, attributes | FileAttributes.Archive);
}
else
{
if (archived)
File.SetAttributes(f.FullName, attributes & ~FileAttributes.Archive);
}
}
}
Now, Guffa has a point about the attributes being cached by FileInfo, though I see this more as an argument against using FileInfo in the first place. I'd prefer to store just the pathname as a string.
I also changed the bit test to compare to zero, which I should have done in the first place. Thanks, KeithS and Guffa.
And, to keep it all in one place, if we were using C# 4.0, we could say:
bool archived = attributes.HasFlag(FileAttributes.Archive);
No, that's pretty standard when dealing with flagged (bitwise rather) values.
You might wanna lose the else if bit, as booleans generally only have 2 states.
In the getter, if the bitwise AND evaluates to any nonzero, the bit's set, so your getter can be shortened somewhat:
get
{
return (((File.GetAttributes(f.FullName)) & FileAttributes.Archive) != 0);
}
Everything else is pretty much optimal; you can lose some parenthesis and one evaluation by getting rid of the braces around the if and else of the setter, and making the "else if" just an "else". Or, combine the inner and outer expressions; really, the inner expressions are not necessary as 1 | 1 == 1 and 1 & ~1 == 0, so setting it to the same value multiple times won't hurt anything.
Related
I have a rather large Flag enum called AmendmentType. I need to check to see that if it has specific Enums and any others.
For Example:
var foo = AmendmentType.Item1;
if (foo.HasFlag(AmendmentType.Item1) && (ANYTHING ELSE))
{
//DO NOT ALLOW
}
else if (foo.HasFlag(AmendmentType.Item2) && foo.HasFlag(AmendmentType.Item6))
{
//DO NOT ALLOW
}
else
{
//ALLOW
}
How would this be possible? There are about 20 different items in the Flag Enum and it seems like there should be an easier way than checking all possible combinations.
If you're only interested in the part you've labeled as "anything else", you can use:
if (foo.HasFlag(AmendmentTypeEnum.Item1) && (foo & ~AmendmentTypeEnum.Item1) != 0)
Or just check that it isn't exactly equal to Item1:
if (foo.HasFlag(AmendmentTypeEnum.Item1) && foo != AmendmentTypeEnum.Item1)
Note that checking for the presence of all of multiple flags only needs a single HasFlag call too:
else if (foo.HasFlag(AmendmentTypeEnum.Item2 | AmendmentTypeEnum.Item6))
(I'd also suggest removing the Enum suffix - it'll be a lot easier to read the code without it :)
Another option would be to set up flags that signify the combinations you're interested in.
var flagComboA = AmendmentTypeEnum.Item1;
var flagComboB = AmendmentTypeEnum.Item2 | AmendmentTypeEnum.Item6;
if(foo == flagComboA || foo == flagComboB)
{
//DO NOT ALLOW
}
Well i got this if else statement where i have 12 variables that can either be 0, 1, or 2. if its a 0 its pass, if its 1 it fails, if its a 2 its unknown. I was wondering if anyone knows a shorter way of writing it in C#
here is what i have to write if there isn't
string pass = "pass";
string fail = "fail";
string unknown = "unknown"
if ( value == 0)
{
test1 = pass;
}
else if (value == 1)
{
test1 = fail;
}
else if (value == 2)
{
test1 = unknown;
}
if ( value1 == 0)
{
test2 = pass;
}
else if (value1 == 1)
{
test2 = fail;
}
else if (value1 == 2)
{
test2 = unknown;
}
.
.
.
if ( value12 == 0)
{
test13 = pass;
}
Let me explain a little more. I have 12 pictures on webpage, that need to be updated, depending on a database for the values. Each picture can be only 1 of 3 options and can change depending on the database. A pass(check mark), a fail(a red x) and an unknown (question mark). Let me know if you need more details.
Well i got this if else statement where i have 12 variables that can either be 0 1 or 2.
Any time you have several variables which you want to be able to treat in a similar way, you should use a collection for them, e.g. an array or a List<T>. If you don't already have a collection for them, you can create one:
int[] values = { value0, value, value2 /* etc * };
... although it would be better if you could have them as a collection from the very start.
Then you can iterate over all of them. It's not really clear why in this case you're overwriting the value of test in each block, but having a collection of inputs ends up with a natural way of creating a collection of outputs. You can also use a switch statement or a conditional expression to make the checks simpler. For example:
public static string ConvertValueToLabel(int value)
{
switch (value)
{
case 0: return "pass";
case 1: return "fail";
case 2: return "unknown";
// Adjust this behaviour as appropriate...
default: throw new ArgumentOutOfRangeException("value");
}
}
Or:
public static string ConvertValueToLabel(int value)
{
// Note that this doesn't do the same range checking as the version above
return value == 0 ? "pass"
: value == 1 ? "fail"
: "unknown";
}
(Some people don't like "stacking" conditionals like this, and I probably wouldn't use it in this case where a switch statement is probably more sensible, but it can be really handy.)
Looks like a case for arrays.
int[] values = { 1, 1, 2, 2, 1, 2 };
for (int i = 0; i < values.Length; i++)
{
if (values[i] == 1)
{
}
else if (values[i] == 2)
{
}
}//for
According to your code there is no need to check values 0-11 cause the test variable is changed again using value12. So you can just check the last value and and skip all other.
I would write a for loop which checks each variable. Or, at the very least, write the check as a function which can be referenced with each variable. Do the former if the variables are in series and their names can be determined sequentially. Do the later if the variable names are not really related to each other.
If necessary, place the variables into an array which can be looped through.
Which is better of the following?
this.isLoggedIn = (bool)HttpContext.Current.Session["li"] == true;
or
this.isLoggedIn = (bool)HttpContext.Current.Session["li"];
It needs be to true ONLY when the session is true. If the session is set to false will this evaluate to true in #2 as it exists? Or is it evaluating its value?
The second one:
this.isLoggedIn = (bool)HttpContext.Current.Session["li"];
(bool)HttpContext.Current.Session["li"] is already a boolean (so will be either true or false), so no need for the extra comparison and return value of the boolean expression.
Either way, you need to check that the li session variable exists before trying to cast it, or your code will throw (I think a NullReferenceException).
The latter is clearer, IMO. They're functionally equivalent though - in both cases, it will fetch the value of "li" from the session and attempt to cast it to bool, throwing an exception if the value isn't present.
Create a property for the desired value:
public bool IsLoggedIn {
get { return (bool)HttpContext.Current.Session["li"]; }
}
You could even go one extra level, if the session is used a lot in the class:
public bool IsLoggedIn {
get { return (bool)Session["li"]; }
}
private HttpSessionState Session {
get { return HttpContext.Current.Session; }
}
Also, if you ever want to look at the session by itself, use a better key, like "IsLoggedIn", instead of "li".
It might be good to create a special class for these application-wide values:
public static class MyAppSession {
const string IsLoggedInKey = "IsLoggedIn";
public static bool IsLoggedIn {
get {
return Session[IsLoggedInKey] != null && (bool)Session[IsLoggedInKey];
}
internal set { Session[IsLoggedInKey] = value; }
}
// ...
private static HttpSessionState Session {
get { return HttpContext.Current.Session; }
}
}
The first and the second approach is equivalent, but the first one is to verbose for my taste. I like the second one much better.
Just as I like this
bool accepted = true;
if( accepted)
{
..
}
Better than
bool accepted = true;
if( accepted == true)
{
..
}
I feel it clearer that way if the variables are properly named.
Just put the expected value in the place of the expression, and it will become pretty clear:
First example:
Before: this.isLoggedIn = (bool)HttpContext.Current.Session["li"] == true;
After: this.isLoggedIn = true == true;
Second example:
Before: this.isLoggedIn = (bool)HttpContext.Current.Session["li"];
After: this.isLoggedIn = true;
Now, try the same for the false case:
First example:
Before: this.isLoggedIn = (bool)HttpContext.Current.Session["li"] == true;
After: this.isLoggedIn = false == true;
Second example:
Before: this.isLoggedIn = (bool)HttpContext.Current.Session["li"];
After: this.isLoggedIn = false;
As you can see, there will be no difference in the result between the two approaches. It all comes down to questions about coding style and readability, where I would guess that you would find a bias towards the shorter version.
You never need to write code that says:
bool x = (y == true);
Instead just use
bool x = y;
In your specific case you should use:
this.isLoggedIn = HttpContext.Current.Session["li"] != null
&& (bool)HttpContext.Current.Session["li"];
This way you will not get an exception if Session["li"] has not been assigned yet. However you will get an exception if Session["li"] is not castable to bool.
I would use the second option with a variant:
this.isLoggedIn = (bool) (HttpContext.Current.Session["li"] ?? "false");
The ?? is null-coalescing operator - it gives a value of "false" to the expression on its lefthand side, in case it happens to be null.
Both pieces of code are equal, so the better is the second (it's shorter).
I have the following log file:
START:SOME_STRING
BL:2
LK:3
LH:5
end
START:SOME_STRING
BL:5
LK:6
LH:6
end
Which has multiple START: -> end structures inside. Is there a better 'non-sloppy' way of parsing this file rather than reading line by line and using SPLIT?
You can try to formalize your ini-file's grammar, and you some of parser generators. See this question for more detail.
Be aware howeveer that for such a simple grammar as yours it might be easier to parse manually :-P
class IniEntry
{
public int BL;
public int LK;
public int LH;
IniEntry Clone() { return new IniEntry { BL = BL, LK = LK, LH = LH }; }
}
IEnumerable<IniEntry> Parse()
{
IniEntry ie = new IniEntry();
while (ParseEntry(out ie))
yield return ie.Clone();
}
bool ParseEntry(out IniEntry ie)
{
ie = new IniEntry();
return ParseStart(ie) &&
ParseBL(ie) &&
ParseLK(ie) &&
ParseLH(ie) &&
ParseEnd(ie);
}
bool ParseStart(IniEntry ie)
{
string dummy;
return ParseLine("START", out dummy);
}
bool ParseBL(IniEntry ie)
{
string BL;
return ParseLine("BL", out BL) && int.TryParse(BL, out ie.BL);
}
bool ParseLK(IniEntry ie)
{
string LK;
return ParseLine("LK", out LK) && int.TryParse(LK, out ie.LK);
}
bool ParseLH(IniEntry ie)
{
string LH;
return ParseLine("LH", out LH) && string.TryParse(LH, out ie.LH);
}
bool ParseLine(string key, out string value)
{
string line = GetNextLine();
var parts = line.Split(":");
if (parts.Count != 2) return false;
if (parts[0] != key) return false;
value = parts[1];
}
etc.
This is a good candidate for a while loop and a state machine.
With this approach you would use even use less memory and have greater performance than using string.split()
If it is certain that the START/END are always matched, (apologies, my C# is embarrassing, so plain English):
Read the whole file with System.IO.ReadToEnd
Parse the whole thing in one go with a regular expression
Iterate over regex results
The regex would be something like "(START:([^$]+)$BL:([^$]+)$LK:([^$]+)$LH:([^$]+)$end$)+", off the top of my head, you'll need to validate/adjust according to how your parameters BL/LK etc. occur
Should be a simple question for the C# experts here.
I basically want to check if one value or another is TRUE, a wild stab at the code is below:
if ((Boolean.Parse(staff.getValue("Male")) | Boolean.Parse(staff.getValue("Female")))
{
// is true
}
Is this correct?
Thanks
If EXACTLY ONE should be true then it is:
var male = bool.Parse(staff.getValue("Male"));
var female = bool.Parse(staff.getValue("Female"));
if (male ^ female)
{
//is true
}
Sounds like you're looking for the logical OR.
if(condition1 || condition2)
{
}
Use the || (double pipe), logical OR.
bool isMale = Boolean.Parse(staff.getValue("Male");
bool isFemale = Boolean.Parse(staff.getValue("Female");
if (isMale || isFemale) // note double pipe ||
{
// do something if true
}
In C# statement expressions are evaluated from left to right. In an OR operation, the second expression will not be evaluated if the first one equals true.
The conditional OR operator || is what you need
if ((Boolean.Parse(staff.getValue("Male")) || Boolean.Parse(staff.getValue("Female")))
{
//is true
}
If the first condition is TRUE, then the second condition isn't checked since the outcome is obviously going to return TRUE.
Note that TryParse works more fast and more safe then just Parse because doesn't throw an exception in case of error. TryParse returns bool that indicates was parse successful or was not.
So both parsing methods should return true and only after that - do the main check
bool male, female;
if ((Boolean.TryParse(staff.getValue("Male"), out male) &&
Boolean.TryParse(staff.getValue("Female"), out female)) &&
(male || female)) // or ^
{
// do stuff
}
or
bool male, female;
if (Boolean.TryParse(staff.getValue("Male"), out male) &&
Boolean.TryParse(staff.getValue("Female"), out female))
{
if(male) { }
else if (female) { } // or just else
}
else
{
// staff contains wrong data. Probably "yeap" instead of "true"
}
To indicate whether a gender is specified with a value of "true" rather than "false",
bool genderIsSpecified = staff.getValue("Male") | staff.getValue("Female");
.. will only determine whether it's one of those values, not which of those values the object staff is.
So, just in case this question is literal and not an abstract example, ...
Male or Female .. everyone is one or the other. Perhaps in your question you meant to ask which of the two is the case? In that case,
bool defaultGenderIfNoGenderDocumented = true; // male
bool MaleIfTrue_FemaleIfFalse = !string.IsNullOrEmpty(staff.getValue("Male"))
? bool.Parse(staff.getValue("Male"))
: string.IsNullOrEmpty(staff.getValue("Female"))
? bool.Parse(staff.getValue("Female"))
? false
: defaultGenderIfNoGenderDocumented
: defaultGenderIfNoGenderDocumented;
Or simply,
// assume value is properly populated, ignore "Female" value
bool isMale = bool.Parse(staff.getValue("Male"));
This is a similar scenario but I am checking for three or more bool values.
Thread th = new Thread(() =>
{
while (true)
{
bool allReadComplete = true;
foreach (IDataProvider provider in lstDataProviders)
{
provider.StartReading();
if (provider.FinishedReading)
allReadComplete = allReadComplete && provider.FinishedReading;
else
allReadComplete = provider.FinishedReading;
}
// to induce some context switching
Thread.Sleep(0);
if (allReadComplete)
break;
}
Console.WriteLine("Thread Exiting");
});
th.IsBackground = true;
th.Start();
A little exception checking is needed anyway. The Boolean.Parse() method gets a string as argument and returns either true or false only if the argument, once stripped out of whitespace, is equal to "True" or "False" (note capitalization). In ANY other case the function returns an exception.
Supposing that the possible values of staff.getValue("Male") and staff.getValue("Female") are exactly those two, then the simple disjunction (||) is sufficient. If any other return value is possible, including null and the empty string, then you have to check for exceptions
bool isMale;
try {
isMale = Boolean.Parse(staff.getValue("Male"));
} catch(Exception e) {
isMale = Boolean.False;
}
try {
isFemale = Boolean.Parse(staff.getValue("Female"));
} catch(Exception e) {
isFemale = Boolean.False;
}
if (isMale || isFemale) // note double pipe ||
{
// do something if true
}
or compare manually
bool isMale = Boolean.TrueValue == staff.getValue("Male");
bool isFemale = Boolean.TrueValue == staff.getValue("Female");
if (isMale || isFemale) // note double pipe ||
{
// do something if true
}