Typ
System.String znany także pod aliasem
string towarzyszy nam przez całe nasze .NET-owe życie. W tym poście przedstawione zostaną pewne mniej znane konstrukcje, które mogą przydać się w codziennej pracy z C#.
W C# ciągi znaków są immutable, co oznacza, że nie można ich modyfikować. Każda operacja modyfikująca utworzy na stercie nową instancję. Typ
System.String dziedziczy po object i implementuje takie interfejsy, jak
IComparable,
ICloneable,
IConvertible,
IEnumerable,
IEquatable. Dodatkowo w C# można deklarować tzw. verbatim strings - ciągi znaków wewnątrz których każdy znak ma być traktowany jako część ciągu znaków - przed takim stringiem umieszczamy
@.
String interning
Jest to technika optymalizująca zużycie pamięci w .NET. Polega ona na tym, że dla każdego ciągu znaków liczony jest hash i taki ciąg znaków wkładany jest do specjalnego słownika, gdzie kluczem jest właśnie ten hash. Słownik istnieje w obrębie całej AppDomain i podczas alokacji nowego string-a, jeżeli wyliczony hash znajduje się w słowniku, to instancja jest reużywana.
Konstruktory
Warto znać przeciążenia konstruktora. Poniżej przykład na to, jak utworzyć ciąg 10 zer na 4 sposoby. Sposób wpisania literal-u wydaje się najprostszy, ale możemy to zrobić na inne, bardziej wygodne sposoby za pomocą konstruktorów.
char[] array = new char[10];
for (int i = 0; i < array.Length; i++)
array[i] = '0';
char[] array2 = new char[12];
for (int i = 0; i < array2.Length; i++)
array2[i] = '0';
Console.WriteLine(new string(array));
Console.WriteLine(new string(array2, 1, array2.Length -2));
Console.WriteLine(new string('0', 10));
Console.WriteLine("0000000000");
StringBuilder
W C# możemy sklejać stringi za pomocą operatora
+. W pewnych sytuacjach (wiele sklejeń) jest on jednak bardzo niewydajny, dlatego zaleca się korzystać z klasy
StringBuilder. Obiekt taki zawiera pole, które wskazuje na tablicę struktur typu Char. StringBuilder pozwala na manipulowanie taką tablicą. Jeżeli przekroczymy zaalokowane miejsce, to StringBuilder automatycznie skopiuje znaki i zbuduje nową tablicę. Wywołanie ToString spowoduje stworzenie nowego obiektu String na stercie i zwrócenie referencji do niego. Domyślna pojemność StringBuildera to 16 znaków. Jeżeli operacje wykonywane na nim próbują przekroczyć pojemność, to StringBuilder podwaja zaalokowane miejsce.
var random = new Random();
var sb = new StringBuilder();
var next = random.Next() % 100;
while (next % 2 == 0)
{
sb.Append(next);
next = random.Next() % 100;
}
Console.WriteLine(sb.ToString());
Instancyjne metody
var str = "Jambalaya";
//IEnumerable extension methods
Console.WriteLine(new string(str.Distinct().ToArray()));
//Walidacja
if(str.EndsWith("ya") && str.StartsWith("Ja") && str.Contains("ala"))
Console.WriteLine("Matches");
Console.WriteLine(new string(str.Except("aya").ToArray())); //Jmbl
//traktuje aya jako IEnumerable<char>
//Analiza
Console.WriteLine(str.IndexOf('a'));
Console.WriteLine(str.IndexOfAny(new char[] {'a', 'J'}));
Console.WriteLine(str.LastIndexOf('a'));
Console.WriteLine(str.LastIndexOfAny(new char[] { 'l', 'y' }));
//Tworzenie nowych instancji
Console.WriteLine(str.Insert(3, "error")); //Jamerrorbalaya
//Uzupełnia podanym znakiem do zadanej długości (20), domyślnie spacja
Console.WriteLine(str.PadLeft(20, '_')); // ___________Jambalaya
Console.WriteLine(str.PadLeft(20)); // Jambalaya
//3 oznacza maksymalną liczbę itemów
var items = str.Split(new char[] {'a'}, 3,
StringSplitOptions.RemoveEmptyEntries); //J,mb,laya
foreach (var item in items)
Console.WriteLine(item);
str += "\n \t";
Console.WriteLine(str.Length); //12
//usuwa wszystkie biale spacje
str = str.Trim();
Console.WriteLine(str.Length); //9
Statyczne metody
var s1 = "me";
var s2 = "Mark";
Console.WriteLine(string.Compare(s1, s2)); //1
var s3 = string.Format("{0} and {1} went to school", s1, s2);
Console.WriteLine(s3);
Console.WriteLine(string.IsNullOrEmpty("")); //true
//drugi argument to params
Console.WriteLine(string.Join(",", s1, s2));
Numeryczne konwersje
float price = 99.99f;
Console.WriteLine("C - currency: " +
price.ToString("C")); //99.99 zł
Console.WriteLine(price.ToString("C",
CultureInfo.CreateSpecificCulture("en-US"))); //$99.99
int num = 70;
Console.WriteLine("D - decimal: " + num.ToString("D4")); //0070
long number = 70000000000000000;
Console.WriteLine("E - exponential: " +
number.ToString("E")); // 7,000000E+016
Console.WriteLine("N - number: " +
number.ToString("N")); // 70 000 000 000 000 000,00
double perc = 0.02;
Console.WriteLine("P - percent: " + perc.ToString("P")); //2,00%
int value = 1024;
Console.WriteLine("X - hexadecimal: " + value.ToString("X4")); //0040