Ich frage mich, auf welche Weise zwei Charaktere richtig miteinander verglichen werden können, wobei der Fall ignoriert wird, der für alle Kulturen gilt. Ist Comparer<char>.Default
der beste Weg, zwei Zeichen zu testen, ohne dabei die Groß- und Kleinschreibung zu ignorieren? Funktioniert das für Ersatzpaare?
EDIT: Beispiel-IComparer<char>
-Implementierung hinzugefügt
Wenn dies jemandem hilft, habe ich mich dazu entschieden
public class CaseInsensitiveCharComparer : IComparer<char> {
private readonly System.Globalization.CultureInfo ci;
public CaseInsensitiveCharComparer(System.Globalization.CultureInfo ci) {
this.ci = ci;
}
public CaseInsensitiveCharComparer()
: this(System.Globalization.CultureInfo.CurrentCulture) { }
public int Compare(char x, char y) {
return Char.ToUpper(x, ci) - Char.ToUpper(y, ci);
}
}
// Prints 3
Console.WriteLine("This is a test".CountChars('t', new CaseInsensitiveCharComparer()));
Es hängt davon ab, was Sie unter "Arbeit für alle Kulturen" verstehen. Möchten Sie, dass "ich" und "ich" auch in der Türkei gleich sind?
Du könntest benutzen:
bool equal = char.ToUpperInvariant(x) == char.ToUpperInvariant(y);
... aber ich bin nicht sicher, ob dies nach Ihrem Verständnis von "Werken" für alle Kulturen "funktioniert".
Natürlich können Sie beide Zeichen in Strings konvertieren und dann den gewünschten Vergleich der Strings durchführen. Etwas weniger effizient, bietet Ihnen jedoch alle im Rahmen verfügbaren Vergleiche:
bool equal = x.ToString().Equals(y.ToString(),
StringComparison.InvariantCultureIgnoreCase);
Für Ersatzpaare ist ein Comparer<char>
sowieso nicht machbar, da Sie keine einzige char
haben. Sie könnten jedoch einen Comparer<int>
erstellen.
Verwenden der Standardkultur (dh nicht der Invariante):
if (char.ToLower(ch1) == char.ToLower(ch2))
{ .... }
Oder spezifizieren Sie eine Kultur:
CultureInfo myCulture = ...;
if (char.ToLower(ch1, myCulture) == char.ToLower(ch2, myCulture))
{ .... }
So wie ich es verstehe, gibt es nicht wirklich einen Weg, "der für alle Kulturen funktioniert". Entweder möchten Sie Zeichen für eine Art interner, nicht für den Benutzer angezeigter Grund vergleichen (in diesem Fall sollten Sie InvariantCulture verwenden), oder Sie möchten die CurrentCulture des Benutzers verwenden. Wenn Sie die aktuelle Kultur des Benutzers verwenden, erhalten Sie natürlich unterschiedliche Ergebnisse in verschiedenen Gebietsschemas. Sie sind jedoch konsistent mit den Erwartungen Ihrer Benutzer in diesen Gebietsschemas.
Ohne mehr über WARUM zu wissen, warum Sie zwei Charaktere vergleichen, kann ich Ihnen nicht wirklich raten, welchen Sie verwenden sollten.
string.Compare ("string a", "STRING A", true)
Es wird für jede Saite funktionieren
Was ich dachte, dass innerhalb der Laufzeit verfügbar sein würde, ist ungefähr wie folgt
public class CaseInsensitiveCharComparer : IComparer<char> {
private readonly System.Globalization.CultureInfo ci;
public CaseInsensitiveCharComparer(System.Globalization.CultureInfo ci) {
this.ci = ci;
}
public CaseInsensitiveCharComparer()
: this(System.Globalization.CultureInfo.CurrentCulture) { }
public int Compare(char x, char y) {
return Char.ToUpper(x, ci) - Char.ToUpper(y, ci);
}
}
// Prints 3
Console.WriteLine("This is a test".CountChars('t', new CaseInsensitiveCharComparer()));
Ich würde empfehlen, Großbuchstaben zu vergleichen, und wenn sie nicht übereinstimmen, dann Kleinbuchstaben vergleichen, nur für den Fall, dass sich die Großbuchstaben und die Kleinbuchstabenlogik des Gebietsschemas etwas anders verhalten.
Nachtrag
Zum Beispiel,
int CompareChar(char c1, char c2)
{
int dif;
dif = char.ToUpper(c1) - char.ToUpper(c2);
if (diff != 0)
dif = char.ToLower(c1) - char.ToLower(c2);
return dif;
}
Du könntest es versuchen:
class Test{
static int Compare(char t, char p){
return string.Compare(t.ToString(), p.ToString(), StringComparison.CurrentCultureIgnoreCase);
}
}
Aber ich bezweifle, dass dies der "optimale" Weg ist, aber ich bin nicht in all den Fällen, die Sie überprüfen müssen ...