I'm in search for some code-improvement. I currently have the following piece of code:
if (pMyDocAction.s_locatie_st != null)
{
String[] myLocaties = Globals.GlobalTools.DeserializeValueToStringArray(pMyDocAction.s_locatie_st);
if (myLocaties != null)
if (myLocaties.Length > 0)
row.Locatie = myLocaties[0];
else
row.Locatie = String.Empty;
else
row.Locatie = String.Empty;
}
else
row.Locatie = String.Empty;
Mylocaties is a Array of String and this cannot change. How can i shorten this piece of code (or how can i combine the != null and .length > 0?
Thnx
You can use conditional operator and write that statement like this:
row.Locatie = (myLocaties != null &&
myLocaties.Length > 0) ? myLocaties[0] : String.Empty
I would suggest you to create a small extension method:
public static class ArrayExtension{
public static bool HasContent<T>(Array<T> array) {
return array != null && array.Length > 0;
}
}
Then you can check :
int[] x = null;
x.HasContent(); // false
string[] strs = new string[] {};
strs.HasContent(); // false
string[] strs2 = new string[] {"foo", "bar" };
strs.HasContent(); // true
This can be extended to simplify your syntax:
public static class ArrayExtension{
public static T FirstValueOrDefault<T>(Array<T> array, T #default) {
if( array != null && array.Length >0 ){
return array[0];
}
else {
return #default;
}
}
}
int[] x = null;
int y = x.FirstValueOrDefault(42); // 42
string[] strs = new string[] {};
string some = strs.FirstValueOrDefault("default"); // default
string[] strs2 = new string[] {"foo", "bar" };
string some2 = strs.FirstValueOrDefault("default"); // foo
Use && operator on two conditions, it will do short-circuit evaluation and if first condition is false, it will not evaluate the second condition.
if (myLocaties != null && myLocaties.Length > 0)
{
row.Locatie = myLocaties[0];
}
else
{
row.Locatie = String.Empty;
}
Since all other answers seem to ignore the if (pMyDocAction.s_locatie_st != null), something like this seems to be the most reusable:
row.Locatie = DeserializeLocation(pMyDocAction.s_locatie_st);
string DeserializeLocation(string locationString)
{
var result = "";
if (!string.IsNullOrEmpty(locationString))
{
String[] deserializedLocations =
Globals.GlobalTools.DeserializeValueToStringArray(locationString);
if (deserializedLocations != null && deserializedLocations.Any())
{
result = deserializedLocations[0];
}
}
return result;
}
You might even consider putting this method in your "GlobalTools" class, so you can call it from anywhere were you need to deserialize a potentially null-bearing serialized location string into a location string.
Related
for instance,
string[] text=new string[] {"string1", "string2", "string3"};
how do i know if all string's length in this array are equal?
Another solution:
bool allSameLength = !text.Any(t => t.Length != text[0].Length));
Here is a solution without using for(each) as requested:
string[] text = new string[] {"dsasaffasfasfafsa", "siuuuuu", "ewqewqeqeqewqeq"};
int index = 0, firstLength = -1;
bool allSameLength = true;
while(index < text.Length)
{
int length = (text[index] + '\0').IndexOf('\0');
firstLength = (index == 0) ? length : firstLength;
allSameLength &= (length != firstLength) ;
index += 1;
}
return allSameLength;
Here is another solution that does not use for(each) and does not try to cheat by using a different type of loop (like while):
string[] text = new string[] {"dsasaffasfasfafsa", "siuuuuu", "ewqewqeqeqewqeq"};
List<string> texts = new List<string>();
texts.Add(null);
texts.AddRange(text);
texts.Add(null);
bool CheckSameLength(int index)
=> (texts[index + 1] == null) ? true
: texts[index] == null ? CheckSameLength(1)
: texts[index].Length == texts[index + 1].Length ? CheckSameLength(index + 1)
: false;
return CheckSameLength(texts, 0);
Most ridiculous use of recursion?
public class Program {
public static void Main() {
string[] text = new string[] {"dsasaffasfasfafsa", "siuuuuu", "ewqewqeqeqewqeq"};
Console.WriteLine(AllLengthsEqual(text));
}
public static bool AllLengthsEqual(string[] strArr) {
return strArr == null ? true : (strArr.Length < 2 ? true : AllLengthsEqual(strArr, 0));
}
private static bool AllLengthsEqual(string[] strArr, int index) {
return AllLengthsEqual(strArr, index + 1, strArr[index] != null ? strArr[index].Length : -1);
}
private static bool AllLengthsEqual(string[] strArr, int index, int prevLength) {
if (index < strArr.Length) {
int thisLength = strArr[index] != null ? strArr[index].Length : -1;
return (thisLength == prevLength) && AllLengthsEqual(strArr, index + 1, thisLength);
}
else
return true;
}
}
I tried following the method as follows here: Checking if Object has null in every property . However, when instantiating Order newOrder = new Order();. I cannot simple just implement bool props = newOrder.ArePropertiesNotNull(). What am I supposed to add to my Order class? And where do I implement the function for ArePropertiesNotNull<T>(this T obj)? I would like to know if there is a way to return false if value returned equals 0 or null?
Here is my code:
OrderProdRepository.cs
...
public bool ReadFromFile(string _date)
{
taxesFile.ReadFile();
productsFile.ReadFile();
string orderFileName = $"C:\\tempfolder\\Orders_{_date}.txt";
List<string> lines = File.ReadAllLines(orderFileName).ToList();
foreach (var line in lines.Skip(1)) //?? new List<string>(0)
{
List<string> entry = line.Split(',').ToList();
Order newOrder = new Order();
int.TryParse(entry[0], out int orderNumber);
newOrder.OrderNumber = orderNumber;
newOrder.Date = _date;
newOrder.CustomerName = entry[1];
newOrder.State = taxesFile.StateAbbreviation(entry[2]);
newOrder.StateName = taxesFile.StateName(newOrder.State);
decimal.TryParse(entry[3], out decimal taxRate);
newOrder.TaxRate = taxesFile.TaxRate(taxRate);
newOrder.ProductType = productsFile.ProductType(entry[4]);
decimal.TryParse(entry[5], out decimal area);
newOrder.Area = area;
decimal.TryParse(entry[6], out decimal costPerSquareFoot);
newOrder.CostPerSquareFoot = productsFile.CostPerSquareFoot(costPerSquareFoot);
decimal.TryParse(entry[7], out decimal laborCostPerSquareFoot);
newOrder.LaborCostPerSquareFoot = productsFile.LaborCostPerSquareFoot(laborCostPerSquareFoot);
decimal.TryParse(entry[8], out decimal materialCost);
newOrder.MaterialCost = materialCost;
decimal.TryParse(entry[9], out decimal laborCost);
newOrder.LaborCost = laborCost;
decimal.TryParse(entry[10], out decimal tax);
newOrder.Tax = tax;
decimal.TryParse(entry[11], out decimal total);
newOrder.Total = total;
orderList.Add(newOrder);
}
return true;
}
...
I think you need a function to check each line for null and/or 0 values:
private bool IsValidLine(string line)
{
if (line == null)
return false;
var arr = line.Split(',');
//Uncomment this if splitting the line will always return 11 items array.
//if (arr.Length < 11)
// return false;
return arr.Aggregate(0, (n, s) =>
(decimal.TryParse(s, out decimal d) && d == 0) ||
string.IsNullOrWhiteSpace(s) ? n + 1 : n) == 0;
}
You can use it in your code as follows:
public bool ReadFromFile(string _date)
{
var orderFileName = $"C:\\tempfolder\\Orders_{_date}.txt";
var lines = File.ReadAllLines(orderFileName);
foreach (var line in lines.Skip(1))
{
//If parsing any line returns false.
if (!IsValidLine(line))
return false;
//Or if you need to create a list of the valid Order entries.
if (IsValidLine(line))
{
var order = new Order();
//...
orderList.Add(newOrder);
}
}
return true;
}
Alternatives:
Add a static function in the Order class to parse a given line and return a new object of Order type if the line is valid. Something like this.
If its not too late, then consider using a local database or serialization. Something like this and maybe this if you don't mind a vb.net example.
You need to create this method an extension method. It should be defined in static class:
public static class ObjectExtensions
{
public static bool ArePropertiesNotNull<T>(this T obj)
{
return typeof(T).GetProperties().All(propertyInfo => propertyInfo.GetValue(obj) != null);
}
}
Is there a difference between using ?? and if (foo == null) {...} else {...} in C#?
The ?? operator will only evaluate your value once, your version likely would evaluate it multiple times.
so
var baz = foo ?? bar;
should get evaluated as
var tmp = foo;
if(tmp == null)
{
tmp = bar;
}
var baz = tmp;
This is difference is important when foo is a function or a property which has a side effect in the getter.
private int _counter1 = 0;
private int _counter2 = 0;
private string Example1()
{
_counter1++;
if(_counter1 % 2 == 0)
return _counter1.ToString();
else
return null;
}
private string Example2()
{
_counter2++;
return _counter2.ToString();
}
Every time you do a var result = Example1() ?? Example2() the value of _counter1 should only go up by one and the value of _counter2 should only go up every other call.
//Equivalent if statement
var tmp = Example1();
if(tmp == null)
{
tmp = Example2();
}
var result = tmp;
I'm trying to use Uri.IsWellFormedUriString but it doesn't work, and question is - why:
class Program
{
static void Main()
{
Console.WriteLine(IsWellFormed(#"C:\Windows"));
Console.WriteLine(IsWellFormed(#"C:\\:\\//Windows32"));
}
public static bool IsWellFormed(string path)
{
string uriString = "file:///" + path;
string wellFormed = uriString.Replace('\\', '/');
return Uri.IsWellFormedUriString(wellFormed, UriKind.Absolute);
}
}
expected true false output but it returns true in both cases. And I'm really confused a bit.
Here is an approach without try/catch, though it may not be optimal:
public static bool IsWellFormed(string path)
{
string path = "C:\\windows\\:ppz";
var isRooted = Path.IsPathRooted(path);
var root = Path.GetPathRoot(path);
var list = path.Split(new char[] {Path.DirectorySeparatorChar}, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < list.Length; i ++)
{
if(i == 0 && isRooted && s[i]+"\\" == root) continue;
if (s[i].Intersect(Path.GetInvalidPathChars()).Count() != 0)
return false;
if (s[i].Intersect(Path.GetInvalidFileNameChars()).Count() != 0)
return false;
}
return true;
}
You can play with your values and see if this fits your task. You can also customize your own lists for invalid chars.
I've done this with balancing Regex's before when I only had one balancing character...but with more balancing characters it gets more complicated and uglier.
For my current purpose, I instead wrote an method to do this by tokenizing the string but it's terribly slow (and terribly inefficient) The most expensive part seems to be the gratuitous Substring usage I'm doing (yeah I know it's bad).
Basically, I want to take the following
hello("(abc d)", efg (hijk)) and,some more<%lmn, "o(\")pq", (xy(z))%>
and end up with
hello("(abc d)", efg (hijk))
[space] (the actual character)
and
,
some more
<%lmn, "o()pq", (xy(z))%>
In other words, I'm splitting on (and I want these included in the array results)
[space]
,
....and I have "balanced grouping strings"
" "
( )
<% %>
...and I have escape characters
\
I'd prefer not to write a whole big parser for this purpose...
Here's the code:
public static IEnumerable<string> SplitNotEnclosed(this string s, IEnumerable<string> separators, Dictionary<string, string> enclosingValues = null, IEnumerable<char> escapeCharacters = null, bool includeSeparators = false, StringComparison comparisonType = StringComparison.Ordinal)
{
var results = new List<string>();
var enclosureStack = new Stack<KeyValuePair<string, string>>();
bool atEscapedCharacter = false;
if (escapeCharacters == null) escapeCharacters = new[] { '\\' };
if (enclosingValues == null) enclosingValues = new[] { "\"" }.ToDictionary(i => i);
var orderedEnclosingValues = enclosingValues.OrderByDescending(i => i.Key.Length).ToArray();
separators = separators.OrderByDescending(v => v.Length).ToArray();
var currentPart = new StringBuilder();
while (s.Length > 0)
{
int addToIndex = 0;
var newEnclosingValue = orderedEnclosingValues.FirstOrDefault(v => s.StartsWith(v.Key, comparisonType));
if (enclosureStack.Count > 0 && !atEscapedCharacter && s.StartsWith(enclosureStack.Peek().Value))
{
addToIndex = enclosureStack.Peek().Value.Length;
enclosureStack.Pop();
}
else if (newEnclosingValue.Key != null && !atEscapedCharacter)
{
enclosureStack.Push(newEnclosingValue);
addToIndex = newEnclosingValue.Key.Length;
}
else if (escapeCharacters.Contains(s[0]) && enclosureStack.Count > 0)
{
atEscapedCharacter = !atEscapedCharacter;
addToIndex = 1;
}
else if (enclosureStack.Count > 0)
{
atEscapedCharacter = false;
addToIndex = 1;
}
if (enclosureStack.Count == 0)
{
string separator = separators.FirstOrDefault(v => s.StartsWith(v, comparisonType));
if (separator != null)
{
if (currentPart.Length > 0) results.Add(currentPart.ToString());
results.Add(separator);
s = s.Substring(separator.Length);
currentPart = new StringBuilder();
addToIndex = 0;
}
else
{
addToIndex = 1;
}
}
currentPart.Append(s.Substring(0, addToIndex));
s = s.Substring(addToIndex);
}
if (currentPart.Length > 0) results.Add(currentPart.ToString());
if (!includeSeparators)
{
results = results.Except(separators).ToList();
}
return results.ToArray();
}