2017-07-21 25 views
6

Potrzebuję przekonwertować niektóre porównania ciągów z vb na C#. Kod vb używa operatorów> i <. Zamierzam zastąpić to standardowymi metodami porównywania ciągów ramowych. Ale jest zachowanie, którego nie rozumiem. Aby to replikować, mam ten testZrozumienie zachowania porównywania ciągów

[TestMethod] 
public void TestMethod2() 
{ 
    string originalCulture = CultureInfo.CurrentCulture.Name; // en-GB 

    var a = "d".CompareTo("t"); // returns -1 
    var b = "T".CompareTo("t"); // returns 1 

    Assert.IsTrue(a < 0, "Case 1"); 
    Assert.IsTrue(b <= 0, "Case 2"); 
} 

Może ktoś wyjaśnić, dlaczego b wraca 1. Mój obecny jest zrozumienie, że jeśli to jest wielkość liter, a następnie „T” powinna poprzedzać „t” w porządku sortowania tj -1 . Jeśli jest to sprawa niewrażliwe byłoby to samo czyli 0

(FYI .Net Framework 4.5.2)

Wiele thx

+0

Czy możesz również pokazać kod VB? –

+2

Dlaczego konkretnie spodziewasz się, że wielkie litery będą poprzedzać małe litery? (Dzieje się tak, jeśli użyjesz * * porządkowego * porównania, co prawda.) –

+0

Czy kod vb zwróci inny niż "1" w "" T ".CompareTo (" t ")'? – Fabio

Odpowiedz

1

Małe litery pojawiają się przed dużymi literami. Dotyczy to zarówno en-GB, jak i InvariantCulture.

Jeśli chcesz zachować zachowanie podobne do ASCII, powinieneś określić dodatkowe opcje porównania.Porządkowa parametr

zobacz:

Przykładowy kod na repl.it:

using System; 
using System.Globalization; 
using System.Collections.Generic; 

class MainClass 
{ 
    public static void Main(string[] args) 
    { 

     //All the following case sensitive comparisons puts d before D 
     Console.WriteLine("D".CompareTo("d")); 
     Console.WriteLine(String.Compare("D", "d", false)); 
     Console.WriteLine(String.Compare("D", "d", false, CultureInfo.InvariantCulture)); 

     //All the following case sensitive comparisons puts capital D before small letter d 
     Console.WriteLine(String.Compare("D", "d", CultureInfo.InvariantCulture, CompareOptions.Ordinal)); 

     //The following is case insensitive 
     Console.WriteLine(String.Compare("D", "d", true)); 

     //The default string ordering in my case is d before D 
     var list = new List<string>(new[] { "D", "d" }); 
     list.Sort(); 
     foreach (var s in list) 
     { 
      Console.WriteLine(s); 
     } 
    } 
} 

//Results on repl.it 
//Mono C# compiler version 4.0.4.0 
// 
//1 
//1 
//1 
//-32 
//0 
//d 
//D 

Powodzenia

Eyal

0

Kolejność sortowania jest oparty na porównaniu obu binarnej lub tekstowej porównanie w zależności od ustawienia opcji Porównaj. - https://docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/operators-and-expressions/comparison-operators

Jak można zauważyć, istnieją dwa sposoby porównywania łańcuchów ... Co jest domyślne?

Instrukcja Porównaj porównanie określa metodę porównania łańcuchów (Binarny lub Tekst). Domyślna metoda porównywania tekstu to Binary. - https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/option-compare-statement

Jak widać Binary jest domyślnym porównaniem. Oznacza to, że każda wielka litera byłaby mniejsza niż jakakolwiek mała litera. tj. "T"<"t" jest prawdziwe, ale także nieintuicyjne: "Z"<"t" i "A"<"t" są również prawdziwe.

Jest więc prawdopodobne, że VB faktycznie nie spełniał swoich oczekiwań i używał porównania równoważnego przekazaniu StringComparer.Ordinal do metody String.Compare. Uwaga Nie mówię tego, czego się spodziewałeś, normalnie, gdy ludzie porównują łańcuchy, które oczekują "normalnych" porównań tekstu.

+0

"Jeśli naprawdę chcesz replikować to zachowanie, możesz dla charby rzucić je na int przed porównaniem, ale dla dłuższego napisu byłoby dużo trudniej replikować." - nie, aby wykonać porównanie porządkowe, użyjesz 'StringComparison.Ordinal', zakładając, że jesteś zadowolony z" binarnej "reprezentacji" UTF-16 ". –

+0

@JonSkeet: Tak, właśnie to edytowałem. Miałem chwilę. ;-) – Chris

0

Jeśli nie podano CompareTo (Stra, Strb) wykorzystuje

CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.None); 

Dla en-GB małe litery są mniejsze niż te wielkie.

Powiązane problemy