Thursday, April 23, 2020

C# Operators Null-coalescing ,Null-conditional and Chaining


C# Local Function use only just once

c# Array SequenceEqual() and Reverse()

C# Collection by its capability, use it wisely


Best Practice C# Make use of AS operator for casting object

Remember to use As operator, here is the simple reason to avoid unnecessary exception is thrown.

With exception


Student s= new Student();
Object o = s;

var newStudent=  (string)o;// Exception casting not possible

As Operator to rescue, AS operator returns null if not compatible else right conversion object type

Student s= new Student();
Object o = s;

var newStudent=  o as string;// Exception casting not possible




Tuesday, April 21, 2020

Join and Set based operation using IEnumerable

Zip method of List is very interesting and very helpful out of box intersect functions where handy . It ignores the non mapping item from two collection list.
namespace FileProcessor
{
class Program
{
static void Main(string[] args)
{
JoinNamesAndAges();
SetOperations();
WriteLine("Press enter to exit");
ReadLine();
}
private static void JoinNamesAndAges()
{
//Sarah
//Gentry
//Amrit
string[] names = File.ReadAllLines("Names.txt");
// 29
// 30
// 40
string[] ages = File.ReadAllLines("Ages.txt");
List<string> namesAndAges = Join(names, ages);
Display(namesAndAges);
List<string> namesAndAges2 = JoinV2(names, ages);
Display(namesAndAges2);
List<(string name, string age)> namesAndAges3 = JoinV3(names, ages);
WriteLine();
WriteLine("Output (tuple):");
foreach (var tuple in namesAndAges3)
{
WriteLine($"{tuple.name},{tuple.age}");
}
//Sarah
//Gentry
//Amrit
//Amelia
string[] namesExtra = File.ReadAllLines("NamesExtra.txt");
List<string> namesAndAges4 = JoinV2(namesExtra, ages);
Display(namesAndAges4);
void Display(IEnumerable<string> strings)
{
WriteLine();
WriteLine("Output:");
foreach (var @string in strings)
{
WriteLine(@string);
}
}
}
private static List<string> Join(string[] names, string[] ages)
{
List<string> joined = new List<string>();
for (int i = 0; i < names.Length; i++)
{
joined.Add($"{names[i]},{ages[i]}");
}
return joined;
}
private static List<string> JoinV2(string[] names, string[] ages)
{
//IEnumerable<string> joined = names.Zip(ages, CombineNameAndAge);
//return joined.ToList();
//return names.Zip(ages, CombineNameAndAge).ToList();
return names.Zip(ages, (name, age) => $"{name},{age}").ToList();
}
private static List<(string name, string age)> JoinV3(string[] names, string[] ages)
{
return names.Zip(ages, (name, age) => (name, age)).ToList();
}
//private static string CombineNameAndAge(string name, string age)
//{
// return $"{name},{age}";
//}
private static void SetOperations()
{
WriteLine();
WriteLine("Please enter first sequence of ints (separated by commas):");
IEnumerable<int> firstSequence = ReadLine().Split(',').Select(x => int.Parse(x));
WriteLine("Please enter second sequence of ints (separated by commas):");
IEnumerable<int> secondSequence = ReadLine().Split(',').Select(x => int.Parse(x));
IEnumerable<int> concat = firstSequence.Concat(secondSequence);
Display(concat, "Concat results");
IEnumerable<int> union = firstSequence.Union(secondSequence);
Display(union, "Union results");
IEnumerable<int> intersect = firstSequence.Intersect(secondSequence);
Display(intersect, "Intersect results");
IEnumerable<int> except = firstSequence.Except(secondSequence);
Display(except, "Except results");
string[] names = new[] { "Sarah", "Gentry", "Amrit" };
IEnumerable<string> namesResult = names.Except(new[] { "Sarah", "Amrit", "Mark" });
Display(namesResult, "String Except results");
void Display<T>(IEnumerable<T> items, string title)
{
WriteLine();
WriteLine(title);
foreach (var item in items)
{
WriteLine(item);
}
}
}
}
}

ReadOnly vs Immutable collection


ReadOnly Gotcha's

If we declared a collection readonly then it is just a wrapper around the source collection. Here is a catch when I say readOnly collection is just a wrapper I mean it refer source as a reference. There is a point when external library refer readonly collection at a given instance it holds say 10 values. Later stage in the code base if the source reference collection is updated with 11 values in it and we don't want the external library to consume that , in such case readOnly library introduces a complication. For our rescue we should use Immutable only when we are certain readOnly refers to a source that can change due to some conditional logic.

External Library- Refer ReadOnly -R


  • R- refer source collection S holds 10 values
  • S- Later in the code we add 11 values which External library shouldn't refer to..
  • R- refer source collection S holds 11 values

public class AppData
{
public ImmutableArray<Country> AllCountries { get; private set; }
public ImmutableDictionary<CountryCode, Country> AllCountriesByKey
{ get; private set; }
public void Initialize(string csvFilePath)
{
CsvReader reader = new CsvReader(csvFilePath);
var countries = reader.ReadAllCountries().OrderBy(x=>x.Name).ToList();
this.AllCountries = countries.ToImmutableArray();
this.AllCountriesByKey = AllCountries.ToImmutableDictionary(x => x.Code);
this.SetupHardCodedTours();
countries.Add(new Country("Lilliput", "LIL", "somewhere", 1_000_000));
}
}




Efficient Use of Dictionary using custom data type

public class AppData
{
public List<Country> AllCountries { get; private set; }
public Dictionary<CountryCode, Country> AllCountriesByKey { get; private set; }
public void Initialize(string csvFilePath)
{
CsvReader reader = new CsvReader(csvFilePath);
this.AllCountries = reader.ReadAllCountries().OrderBy(x => x.Name).ToList();
var dict = AllCountries.ToDictionary(x => x.Code);
this.AllCountriesByKey = dict;
}
}
public class CsvReader
{
private string _csvFilePath;
public CsvReader(string csvFilePath)
{
this._csvFilePath = csvFilePath;
}
public List<Country> ReadAllCountries()
{
List<Country> countries = new List<Country>();
using (StreamReader sr = new StreamReader(_csvFilePath))
{
// read header line
sr.ReadLine();
string csvLine;
while ((csvLine = sr.ReadLine()) != null)
{
countries.Add(ReadCountryFromCsvLine(csvLine));
}
}
return countries;
}
public Country ReadCountryFromCsvLine(string csvLine)
{
string[] parts = csvLine.Split(',');
string name;
string code;
string region;
string popText;
switch (parts.Length)
{
case 4:
name = parts[0];
code = parts[1];
region = parts[2];
popText = parts[3];
break;
case 5:
name = parts[0] + ", " + parts[1];
name = name.Replace("\"", null).Trim();
code = parts[2];
region = parts[3];
popText = parts[4];
break;
default:
throw new Exception($"Can't parse country from csvLine: {csvLine}");
}
// TryParse leaves population=0 if can't parse
int.TryParse(popText, out int population);
return new Country(name, code, region, population);
}
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private AppData AllData { get; } = new AppData();
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
AllData.Initialize(@"F:\Advanced Collections\Code\PopByLargest.csv");
this.DataContext = AllData;
}
private void tbxCountryCode_TextChanged(object sender, TextChangedEventArgs e)
{
string code = tbxCountryCode.Text;
this.grdSelectCountry.DataContext = GetCountryWithCode(code);
}
private Country GetCountryWithCode(string code)
{
if (code.Length != 3)
return null;
AllData.AllCountriesByKey.TryGetValue(new CountryCode(code), out Country result);
return result;
}
}
public class Country
{
public string Name { get; }
public CountryCode Code { get; }
public string Region { get; }
public int Population { get; }
public Country(string name, string code, string region, int population)
{
this.Name = name;
this.Code = new CountryCode(code);
this.Region = region;
this.Population = population;
}
public override string ToString() => $"{Name} ({Code})";
}
public class CountryCode
{
public string Value { get; }
public CountryCode(string value)
{
Value = value;
}
public override string ToString() => Value;
public override bool Equals(object obj)
{
if (obj is CountryCode other)
return StringComparer.OrdinalIgnoreCase.Equals(this.Value, other.Value);
return false;
}
public override int GetHashCode() =>
StringComparer.OrdinalIgnoreCase.GetHashCode(this.Value);
public static bool operator ==(CountryCode lhs, CountryCode rhs)
{
if (lhs != null)
return lhs.Equals(rhs);
else
return rhs == null;
}
public static bool operator !=(CountryCode lhs, CountryCode rhs)
{
return !(lhs == rhs);
}
}
view raw dictionary.cs hosted with ❤ by GitHub
Country Name Country Code Continent Population 2017
China CHN Asia 1386395000
India IND Asia 1339180127
United States USA North America 325719178
Indonesia IDN Asia 263991379
Brazil BRA South America 209288278
Pakistan PAK Asia 197015955
Nigeria NGA Africa 190886311
Bangladesh BGD Asia 164669751
Russian Federation RUS Europe 144495044
Mexico MEX North America 129163276
Japan JPN Asia 126785797
Ethiopia ETH Africa 104957438
Philippines PHL Asia 104918090
Egypt, Arab Rep. EGY Africa 97553151
Vietnam VNM Asia 95540800
Germany DEU Europe 82695000
Congo, Dem. Rep. COD Africa 81339988
Iran, Islamic Rep. IRN Asia 81162788
Turkey TUR Asia 80745020
Thailand THA Asia 69037513
France FRA Europe 67118648
United Kingdom GBR Europe 66022273
Italy ITA Europe 60551416
Tanzania TZA Africa 57310019
South Africa ZAF Africa 56717156
Myanmar MMR Asia 53370609
Korea, Rep. KOR Asia 51466201
Kenya KEN Africa 49699862
Colombia COL South America 49065615
Spain ESP Europe 46572028
Ukraine UKR Europe 44831159
Argentina ARG South America 44271041
Uganda UGA Africa 42862958
Algeria DZA Africa 41318142
Sudan SDN Africa 40533330
Iraq IRQ Asia 38274618
Poland POL Europe 37975841
Canada CAN North America 36708083
Morocco MAR Africa 35739580
Afghanistan AFG Asia 35530081
Saudi Arabia SAU Asia 32938213
Uzbekistan UZB Asia 32387200
Peru PER South America 32165485
Venezuela, RB VEN South America 31977065
Malaysia MYS Asia 31624264
Angola AGO Africa 29784193
Mozambique MOZ Africa 29668834
Nepal NPL Asia 29304998
Ghana GHA Africa 28833629
Yemen, Rep. YEM Asia 28250420
Madagascar MDG Africa 25570895
Korea, Dem. People�s Rep. PRK Asia 25490965
Australia AUS Oceania 24598933
Cote d'Ivoire CIV Africa 24294750
Cameroon CMR Africa 24053727
Niger NER Africa 21477348
Sri Lanka LKA Asia 21444000
Romania ROU Europe 19586539
Burkina Faso BFA Africa 19193382
Malawi MWI Africa 18622104
Mali MLI Africa 18541980
Syrian Arab Republic SYR Asia 18269868
Chile CHL South America 18054726
Kazakhstan KAZ Asia 18037646
Netherlands NLD Europe 17132854
Zambia ZMB Africa 17094130
Guatemala GTM North America 16913503
Ecuador ECU South America 16624858
Zimbabwe ZWE Africa 16529904
Cambodia KHM Asia 16005373
Senegal SEN Africa 15850567
Chad TCD Africa 14899994
Somalia SOM Africa 14742523
Guinea GIN Africa 12717176
South Sudan SSD Africa 12575714
Rwanda RWA Africa 12208407
Tunisia TUN Africa 11532127
Cuba CUB North America 11484636
Belgium BEL Europe 11372068
Benin BEN Africa 11175692
Bolivia BOL South America 11051600
Haiti HTI North America 10981229
Burundi BDI Africa 10864245
Dominican Republic DOM North America 10766998
Greece GRC Europe 10760421
Czech Republic CZE Europe 10591323
Portugal PRT Europe 10293718
Sweden SWE Europe 10067744
Azerbaijan AZE Asia 9862429
Hungary HUN Europe 9781127
Jordan JOR Asia 9702353
Belarus BLR Europe 9507875
United Arab Emirates ARE Asia 9400145
Honduras HND North America 9265067
Tajikistan TJK Asia 8921343
Austria AUT Europe 8809212
Israel ISR Asia 8712400
Switzerland CHE Europe 8466017
Papua New Guinea PNG Oceania 8251162
Togo TGO Africa 7797694
Sierra Leone SLE Africa 7557212
Hong Kong SAR, China HKG Asia 7391700
Bulgaria BGR Europe 7075991
Serbia SRB Europe 7022268
Lao PDR LAO Asia 6858160
Paraguay PRY South America 6811297
El Salvador SLV North America 6377853
Libya LBY Africa 6374616
Nicaragua NIC North America 6217581
Kyrgyz Republic KGZ Asia 6201500
Lebanon LBN Asia 6082357
Denmark DNK Europe 5769603
Turkmenistan TKM Asia 5758075
Singapore SGP Asia 5612253
Finland FIN Europe 5511303
Slovak Republic SVK Europe 5439892
Norway NOR Europe 5282223
Congo, Rep. COG Africa 5260750
Costa Rica CRI North America 4905769
Ireland IRL Europe 4813608
New Zealand NZL Oceania 4793900
Liberia LBR Africa 4731906
West Bank and Gaza PSE Asia 4684777
Central African Republic CAF Africa 4659080
Oman OMN Asia 4636262
Mauritania MRT Africa 4420184
Kuwait KWT Asia 4136528
Croatia HRV Europe 4125700
Panama PAN North America 4098587
Georgia GEO Asia 3717100
Moldova MDA Europe 3549750
Bosnia and Herzegovina BIH Europe 3507017
Uruguay URY South America 3456750
Puerto Rico PRI North America 3337177
Mongolia MNG Asia 3075647
Armenia ARM Asia 2930450
Jamaica JAM North America 2890299
Albania ALB Europe 2873457
Lithuania LTU Europe 2827721
Qatar QAT Asia 2639211
Namibia NAM Africa 2533794
Botswana BWA Africa 2291661
Lesotho LSO Africa 2233339
Gambia, The GMB Africa 2100568
Macedonia, FYR MKD Europe 2083160
Slovenia SVN Europe 2066748
Gabon GAB Africa 2025137
Latvia LVA Europe 1940740
Guinea-Bissau GNB Africa 1861283
Kosovo XKX Europe 1830700
Bahrain BHR Asia 1492584
Trinidad and Tobago TTO North America 1369125
Eswatini SWZ Africa 1367254
Estonia EST Europe 1315480
Timor-Leste TLS Asia 1296311
Equatorial Guinea GNQ Africa 1267689
Mauritius MUS Africa 1264613
Cyprus CYP Asia 1179551
Djibouti DJI Africa 956985
Fiji FJI Oceania 905502
Comoros COM Africa 813912
Bhutan BTN Asia 807610
Guyana GUY South America 777859
Macao SAR, China MAC Asia 622567
Montenegro MNE Europe 622471
Solomon Islands SLB Oceania 611343
Luxembourg LUX Europe 599449
Suriname SUR South America 563402
Cabo Verde CPV Africa 546388
Malta MLT Europe 465292
Maldives MDV Asia 436330
Brunei Darussalam BRN Asia 428697
Bahamas, The BHS North America 395361
Belize BLZ North America 374681
Iceland ISL Europe 341284
Barbados BRB North America 285719
French Polynesia PYF Oceania 283007
New Caledonia NCL Oceania 280460
Vanuatu VUT Oceania 276244
Sao Tome and Principe STP Africa 204327
Samoa WSM Oceania 196440
St. Lucia LCA North America 178844
Channel Islands CHI Europe 165314
Guam GUM Oceania 164229
Curacao CUW North America 161014
Kiribati KIR Oceania 116398
St. Vincent and the Grenadines VCT North America 109897
Tonga TON Oceania 108020
Grenada GRD North America 107825
Virgin Islands (U.S.) VIR North America 107268
Micronesia, Fed. Sts. FSM Oceania 105544
Aruba ABW North America 105264
Antigua and Barbuda ATG North America 102012
Seychelles SYC Africa 95843
Isle of Man IMN Europe 84287
Andorra AND Europe 76965
Dominica DMA North America 73925
Bermuda BMU North America 65441
Cayman Islands CYM North America 61559
Greenland GRL North America 56171
American Samoa ASM Oceania 55641
St. Kitts and Nevis KNA North America 55345
Northern Mariana Islands MNP Oceania 55144
Marshall Islands MHL Oceania 53127
Faroe Islands FRO Europe 49290
Sint Maarten (Dutch part) SXM North America 41109
Monaco MCO Europe 38695
Liechtenstein LIE Europe 37922
Turks and Caicos Islands TCA North America 35446
Gibraltar GIB Europe 34571
San Marino SMR Europe 33400
St. Martin (French part) MAF North America 32125
British Virgin Islands VGB North America 31196
Palau PLW Oceania 21729
Nauru NRU Oceania 13649
Tuvalu TUV Oceania 11192
Eritrea ERI Africa ..
view raw Population.csv hosted with ❤ by GitHub

 Note
The speed of retrieval depends on the quality of the hashing algorithm of the type specified for TKey.

Dictionary generic class provides a mapping from a set of keys to a set of values. Each addition to the dictionary consists of a value and its associated key. Retrieving a value by using its key is very fast, close to O(1), because the Dictionary class is implemented as a hash table.



Monday, April 20, 2020

Performance List.Remove(T) Method is an O(n) operation

List.Remove(T) Method

If type T implements the IEquatable generic interface, the equality comparer is the Equals method of that interface; otherwise, the default equality comparer is Object.Equals.
This method performs a linear search; therefore, this method is an O(n) operation, where n is Count.

Performance List.Item[Int32] Property is O(1) operation

List.Item[i] is O(1) operation

Reason : There is a very large data list and suppose system wants to lookup for 9999 some element in the list. The operation performed to located is one step that is current location+ 9999= 0+9999

Gets or sets the element at the specified index.
C#
public T this[int index] { get; set; }
List accepts null as a valid value for reference types and allows duplicate elements.
This property provides the ability to access a specific element in the collection by using the following syntax: myCollection[index].
Retrieving the value of this property is an O(1) operation; setting the property is also an O(1) operation.

Sunday, April 19, 2020

C# Short circuiting vs Non Short Circuiting logical condition

Short Circuit use && just check first condition and decide the outcome whereas & will evaluate all and conditions. Non short circuit may increase cyclomatic complexity.

How to Use Keywords as Variable Names @csharp

Use Keywords as Variable Names in #csharp var @string= string.Empty;
@string = "We can use keyword string as variable name, cool huh! trick compiler, we know better.."
In case, if you want to use Keywords as variable names (identifiers), then you need to include @ as a prefix for your variable names. For example, @switch is a valid identifier but the switch is not because it's a keyword and having a special meaning for the compiler.