What is a best way for refactor "if" statements?
My method fragment:
if (code == SystemCode.Enum1.ToString())
{
user.IsEnum1 = result != null;
}
if (code == SystemCode.Enum2.ToString())
{
user.IsEnum2 = result != null;
}
if (code == SystemCode.Enum3.ToString())
{
user.IsEnum3 = result != null;
}
I would try this approach:
enum MyEnum
{
Enum1,
Enum2,
Enum3
}
class User
{
Dictionary<MyEnum, bool> enumList;
public void InitEnumList()
{
enumList = new Dictionary<MyEnum, bool>();
foreach (var item in Enum.GetValues(typeof(MyEnum)))
{
//Set the default key-value pairs
enumList.Add((MyEnum)item, false);
}
}
}
Switch statement is one of the good option for avoiding multiple if statements
Try this:
if (( !(code != ((int)SystemCode.Enum1).ToString() || (user.IsEnum1 = result != null).ToString().Length > 0))
|| !(code != ((int)SystemCode.Enum2).ToString() || (user.IsEnum2 = result != null).ToString().Length > 0)
|| !(code != ((int)SystemCode.Enum3).ToString() || (user.IsEnum3 = result != null).ToString().Length > 0))
{
return;
}
I know it looks complex but isn't that what you wanted. Let me know if you have any queries.
Related
So I have a fitler TextBox where I want to search for different type of docs in a grid the code where I have different type of columns such as: Date,DocId,ClientId.
For a search I write on a filter Textbox something like that DocId:2002 and It just work fine but when I try to make a multiple search for example DocId:2002 ClientId:201 It doesnt search because of the return it just does an infinite loop.
private void TextBoxFilter_TextChanged(object sender, TextChangedEventArgs e)
{
foreach (Match m in Regex.Matches((sender as TextBox).Text, pattern, options))
{
if (m.Value != "")
{
Func<String, String> untilSlash = (s) => { return filters[re.Match(s).Groups[1].ToString()] = re.Match(s).Groups[2].ToString(); };
untilSlash(m.Value);
}
}
ICollectionView cv = CollectionViewSource.GetDefaultView(this.DataGridDocList.ItemsSource);
if (filters.Count == 0)
{
cv.Filter = null;
}
else
{
cv.Filter = o =>
{
for (int i = 0; i < filters.Count; i++)
{
if (filters.ElementAt(i).Key == "Date")
{
if (DateVerify.Match(filters.ElementAt(i).Value).Success)
{
return (o as Document).DateCreated < Convert.ToDateTime(DateVerify.Match(filters.ElementAt(i).Value).Groups[1].ToString()) && (o as Document).DateCreated > Convert.ToDateTime(DateVerify.Match(filters.ElementAt(i).Value).Groups[2].ToString());
}
else
{
var dateString = (o as Document).DateCreated.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
return dateString.Contains(DateVerify.Match(filters.ElementAt(i).Value).Groups[1].ToString());
}
}
if (filters.ElementAt(i).Key == "DocId")
{
return (o as Document).DocumentId.ToString().Contains(filters.ElementAt(i).Value);
}
if (filters.ElementAt(i).Key == "ClientId")
{
return (o as Document).ClientId.ToUpper().Contains(filters.ElementAt(i).Value.ToUpper());
}
}
return false;
};
filters.Clear();
}
}
So my question is how can I do an big search with all the filters at one time?
Manually I can add them 1 by 1 and it will be something like search1 && search2 && search3 but It will take too much time and It's probably not the best solution
There are many ways of building up the predicate. However my suggestion is to keep it simple and just create one method that returns true or false. It's good practice to only return once in a method.
The code below if for illustration purposes (as I'm unable to test it):
ICollectionView cv = CollectionViewSource.GetDefaultView(this.DataGridDocList.ItemsSource);
if (filters.Any())
{
cv.Filter = new Predicate<object>(PredicateFilter);
}
else
{
cv.Filter = null;
}
Then Predicate method to filter results:
public bool PredicateFilter(object docObj)
{
Document doc = docObj as Document;
var response = new List<bool>();
for (int i = 0; i < filters.Count; i++)
{
if (filters.ElementAt(i).Key == "Date")
{
if (DateVerify.Match(filters.ElementAt(i).Value).Success)
{
response.Add(doc.DateCreated < Convert.ToDateTime(DateVerify.Match(filters.ElementAt(i).Value).Groups[1].ToString()) && doc.DateCreated > Convert.ToDateTime(DateVerify.Match(filters.ElementAt(i).Value).Groups[2].ToString()));
}
else
{
var dateString = doc.DateCreated.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture);
response.Add(dateString.Contains(DateVerify.Match(filters.ElementAt(i).Value).Groups[1].ToString()));
}
}
else if (filters.ElementAt(i).Key == "DocId")
{
response.Add(doc.DocumentId.ToString().Contains(filters.ElementAt(i).Value));
}
else if (filters.ElementAt(i).Key == "ClientId")
{
response.Add(doc.ClientId.ToUpper().Contains(filters.ElementAt(i).Value.ToUpper()));
}
}
return response.All(m => m); // if all filters came back with true, return 1 response of true else false.
}
I'm swapping my values in List Object on some conditions and update List Object value.
Currently, what I'm doing is
- Looping on each object through List
- Check If condition is net
- Swap values
public static void SwapMinMaxIfNull<T>(this IEnumerable<T> rows, string reportfor)
{
if (reportfor.Equals("Comparison"))
{
var row = rows as IEnumerable<RiskBoardDataToExport>;
try
{
if (rows.Any())
{
var Tests = row.Where(min => min.MinGaitSpeed == null && min.MaxGaitSpeed != null).ToList();
if (Tests != null)
{
foreach (RiskBoardDataToExport test in Tests)
{
test.MinGaitSpeed = test.MaxGaitSpeed;
test.MaxGaitSpeed = null;
}
}
// again check for next object
Tests = row.Where(min => min.MinTUGTime == null && min.MaxTUGTime != null).ToList();
if (Tests != null)
{
foreach (RiskBoardDataToExport test in Tests)
{
test.MinTUGTime = test.MaxTUGTime;
test.MaxTUGTime = null;
}
}
// again check for next object
Tests = row.Where(min => min.MinBergScoreSpeed == null && min.MaxBergScoreSpeed != null).ToList();
if (Tests != null)
{
foreach (RiskBoardDataToExport test in Tests)
{
test.MinBergScoreSpeed = test.MaxBergScoreSpeed;
test.MaxBergScoreSpeed = null;
}
}
//.. for brevity
}
}
}
Can I do it in better way? I know about PropertyInfo i.e. Can check property name and get value etc, but, not having any hint to get this done.
Thanks
It's not exactly what you're asking for, but you can combine the clauses in your Where statements and then have a few if statements in the body:
public static void SwapMinMaxIfNull(this IEnumerable<RiskBoardDataToExport> rows,
string reportfor)
{
if (rows = null) return;
if (reportfor.Equals("Comparison", StringComparison.OrdinalIgnoreCase))
{
foreach (var row in rows.Where(r =>
(r.MinGaitSpeed == null && r.MaxGaitSpeed != null) ||
(r.MinBergScoreSpeed == null && r.MaxBergScoreSpeed != null) ||
(r.MinBergScoreSpeed == null && r.MaxBergScoreSpeed != null)))
{
if (row.MinGaitSpeed == null)
{
row.MinGaitSpeed = row.MaxGaitSpeed;
row.MaxGaitSpeed = null;
}
if (row.MinTUGTime == null)
{
row.MinTUGTime = row.MaxTUGTime;
row.MaxTUGTime = null;
}
if (row.MinBergScoreSpeed == null)
{
row.MinBergScoreSpeed = row.MaxBergScoreSpeed;
row.MaxBergScoreSpeed = null;
}
}
}
}
As this is an operation where order of the items in the list does not matter, you can easily speed this up by parallelization (you can read up on that here).
So, what you should do, is handle this foreach loop in a parallel way and combine it with Rufus L's optimized code for the fastest result.
var rows = rows.Where(r =>
(r.MinGaitSpeed == null && r.MaxGaitSpeed != null) ||
(r.MinBergScoreSpeed == null && r.MaxBergScoreSpeed != null) ||
(r.MinBergScoreSpeed == null && r.MaxBergScoreSpeed != null))
Parallel.ForEach(rows, (row) => {
{
if (row.MinGaitSpeed == null)
{
row.MinGaitSpeed = row.MaxGaitSpeed;
row.MaxGaitSpeed = null;
}
if (row.MinTUGTime == null)
{
row.MinTUGTime = row.MaxTUGTime;
row.MaxTUGTime = null;
}
if (row.MinBergScoreSpeed == null)
{
row.MinBergScoreSpeed = row.MaxBergScoreSpeed;
row.MaxBergScoreSpeed = null;
}
}
Note that this requires the System.Threading.Tasks namespace, that's where the Parallel class is.
i started with this! and i would like to avoid this
private IQueryable<Customer> FilterResult(string search, List<Customer> dtResult, List<string> columnFilters)
{
IQueryable<Customer> results = dtResult.AsQueryable();
results = results.Where(p => (search == null || (p.Name != null && p.Name.ToLower().Contains(search.ToLower()) || p.City != null && p.City.ToLower().Contains(search.ToLower())
&& (columnFilters[0] == null || (p.Name != null && p.Name.ToLower().Contains(columnFilters[0].ToLower())))
&& (columnFilters[1] == null || (p.City != null && p.City.ToLower().Contains(columnFilters[1].ToLower())))
);
return results;
}
by using reflection maybe.... because imagine i have 100 properties it would be easy to mess up ...so i tried this way i would like to use reflection to loop on all properties instead of making references to each of them(properties)
public IQueryable<Aangifte> FilterColumn<T>()
{
try
{
List<Aangifte> v = AangifteGetData.GetData(StartDate, EndDate);
List<Aangifte> v2 = new List<Aangifte>();
Aangifte Foo = new Aangifte();
List<string> propertEntity = new List<string>();
var search = Request.Form.GetValues("search[value]").FirstOrDefault();
int count = -1;
var results = v.AsQueryable();
List<string> columnName = new List<string>();
foreach (var prop in Foo.GetType().GetProperties())
{
var t = "";
if (!prop.Name.Contains("FORMAT"))
{
TVALUE = prop.GetValue(Foo, null);
t= prop.Name;
propertEntity.Add(t);
count++;
}
if (count < propertEntity.Count())
{
var newt = t;
var Z = Request.Form.GetValues("columns[" + count + "][search][value]").FirstOrDefault();
results = results.Where
(
p => (search == null || (t != null && t.ToLower().Contains(search.ToLower())))
&& (Request.Form.GetValues("columns[" + count + "][search][value]").FirstOrDefault() == null || (t != null && t.ToLower().Contains(Request.Form.GetValues("columns[" + count + "][search][value]").FirstOrDefault().ToLower())))
);
}
}
return results;
}
catch (Exception EX)
{
throw EX;
}
}
the code
Settings setting_ = .... // not null
foreach( var item in ItemsCollection)
{
var tt1 = item.GetTT1();
var tt2 = item.GetTT2();
if( tt2 != null && tt1 != null )
{
if( !string.IsNullOrEmpty( settings_.Name ) )
{
tt2.Rename( tt1, setting_.Name );
}
if( setting_ .Settings != null )
{
tt2.ChangeSettings( tt1, setting_.Settings );
}
if( setting_ .Location != null )
{
tt2.ChangeLocation( tt1, setting_.Location );
}
}
}
Because the setting_ is not change at any iteration of the foreach loop => i need to check only once the 3 if .... ( before get into the foreach loop )
But the tt1 & tt2 are change each foreach iteration ...
How can i write this code better with only one check of the setting_ ?
one possible is this
private void defineAction( TT1 tt1 , TT2 tt2, Setting setting )
{
List<Action> action = new List<Action>();
if( !string.IsNullOrEmpty( settings_.Name ) )
{
action.Add( () => tt2.Rename( tt1, setting_.Name )
}
if( setting_ .Settings != null )
{
action.Add( () => tt2.ChangeSettings( tt1, setting_.Settings );
}
if( setting_ .Settings != null )
{
action.Add( () => tt2.ChangeLocation( tt1, setting_.Location );
}
}
and use the List to make the action ..
but i need to call this method each iteration and i want to make it better
Now that I understand from your previous comments what you're trying to do you can create a collection of actions rather than using simple if statements. If may or may not be better performing, since you'd have the cost of the iterator. If the collection is large, it would probably be useful to check if you're going to do anything before iterating over it.
Settings setting_ = .... // not null
var actions = new List<Action<TT1,TT2>>();
if (!string.IsNullOrEmpty(setting_.Name))
{
actions.Add((t1,t2) => t2.Rename(t1, setting_.Name););
}
if (setting_.Settings != null)
{
actions.Add((t1,t2) => t2.ChangeSettings(t1, settings_.Settings));
}
if (setting_.Location != null)
{
actions.Add((t1,t2) => t2.ChangeLocation(t1, settings_.Location));
}
if (actions.Any())
{
foreach( var item in ItemsCollection)
{
var tt1 = item.GetTT1();
var tt2 = item.GetTT2();
if (tt1 == null || tt2 == null)
{
continue;
}
foreach (var action in actions)
{
action(tt1,tt2);
}
}
}
Though I still think it's easier if you just precompute the conditions - I was confused by setting_.Settings before.
Settings setting_ = .... // not null
var changeName = !string.IsNullOrEmpty(setting_.Name);
var changeSetting = setting_.Settings != null;
var changeLocation = setting_.Location != null;
if (changeName || changeSetting || changeLocation)
{
foreach (var item in ItemCollection)
{
var tt1 = item.getTT1();
var tt2 = item.getTT2();
if (tt1 == null || tt2 == null)
{
continue;
}
if (changeName)
{
tt2.Rename(tt1, setting_.Name);
}
if (changeSetting)
{
tt2.ChangeSettings(tt1, settings_.Settings);
}
if (changeLocation)
{
tt2.ChangeLocation(tt1, settings_.Location);
}
}
}
It took me a while to decipher your question but I think I understand you. Here's what you could do:
var actions = new List<Action<Item, Item>>();
if (!string.IsNullOrEmpty(setting_.Name))
{
actions.Add((tt1, tt2) =>
{
if (tt1 != null && tt2 != null)
tt2.Rename(tt1, setting_.Name);
});
}
if (setting_.Settings != null)
{
actions.Add((tt1, tt2) =>
{
if (tt1 != null && tt2 != null)
tt2.ChangeSettings(tt1, setting_.Settings);
});
}
if (setting_.Settings != null)
{
actions.Add((tt1, tt2) =>
{
if (tt1 != null && tt2 != null)
tt2.ChangeLocation(tt1, setting_.Location);
});
}
foreach (var item in itemCollection)
{
var tt1 = item.GetTT1();
var tt2 = item.GetTT2();
actions.ForEach(a => a(tt1, tt2));
}
I'm trying to use the following and can't wrap my head around why this IndexOf method isn't working.
foreach (string s in regKey.GetSubKeyNames())
{
RegistryKey sub = Registry.LocalMachine.OpenSubKey(string.Format(#"{0}\{1}", _UninstallKey64Bit, s), false);
if (sub.ValueCount > 0)
{
values = sub.GetValueNames();
if (IndexOf(values, "DisplayName") != -1)
{
string name = (sub.GetValue("DisplayName") != null) ? sub.GetValue("DisplayName").ToString() : string.Empty;
if (!string.IsNullOrEmpty(name) && (name.ToLower() == appName.ToLower()))
if (IndexOf(values, "UninstallString") != -1)
{
uninstallValue = (sub.GetValue("UninstallString") != null) ? sub.GetValue("UninstallString").ToString() : string.Empty;
break;
}
}
}
}
Can anyone lend me a hand with this?
Correct syntax is:
if (Array.IndexOf(values, "DisplayName") != -1)
GetValueNames() returns a string array so you probably are looking for:
if (values.Contains("DisplayName"))
Try
if (values.Any(v => v == "DisplayName")) )
{
...
}
Try changing -
if (IndexOf(values, "UninstallString") != -1)
to
if (Array.IndexOf(values, "UninstallString") != -1)
Try this instead of just IndexOf.
Array.IndexOf(values, "DisplayName")