2009-11-25 8 views
32

Usando C# y .NET 3.5, ¿cuál es la mejor manera de manejar esta situación? Tengo cientos de campos para comparar de varias fuentes (principalmente cadenas). A veces, la fuente devuelve el campo de cadena como nulo y, a veces como vacío. Y, por supuesto, a veces hay texto en los campos. Mi comparación actual de strA! = StrB no es cortarla porque strA es nula y strB es "", por ejemplo. Sé que podría hacer el string.IsNullOrEmpty que da como resultado una comparación doble y algo de fealdad. ¿Hay una mejor manera de manejar esto? Pensé en métodos de extensión, pero no puedes extender operadores.Cadena Compara dónde nulo y vacío son iguales

Supongo que estoy buscando una manera sexy de hacer esto.

+2

¿Puede usted sin thave la "fuente" devuelve la cadena vacía, o es deseable tener una cadena nula disponibles? –

Respuesta

51

ya que tienes cientos de comparaciones que se pueden hacer, suena como desea una sola función para llamar para que pueda reducir el desorden y la repetición en su código. Creo que no hay una función incorporada para hacer un nulo/cadena vacía/comparación comprobar todo en uno, pero sólo podía hacer uno mismo:

static class Comparison 
{ 
    public static bool AreEqual(string a, string b) 
    { 
     if (string.IsNullOrEmpty(a)) 
     { 
      return string.IsNullOrEmpty(b); 
     } 
     else 
     { 
      return string.Equals(a, b); 
     } 
    } 
} 

A continuación, sólo podría utilizar una sola llamada a su función para cada comparación:

 if(Comparison.AreEqual(strA[0], strB[0])) { // ... } 
     if(Comparison.AreEqual(strA[1], strB[1])) { // ... } 
     if(Comparison.AreEqual(strA[2], strB[2])) { // ... } 
     if(Comparison.AreEqual(strA[3], strB[3])) { // ... } 

Este enfoque es también más fácil de ampliar si posteriormente se descubre que necesita que preocuparse de situaciones adicionales, como ignorando espacios en blanco al principio o al final de las cadenas; entonces puede agregar más lógica a su función para hacer algunos recortes o lo que sea y no tendrá que hacer ninguna modificación a los cientos de líneas de código que llaman a su función.

+0

String.Equals (a, b) también maneja la comparación nula, por lo tanto puede deshacerse de la cadena.IsNullOrEmpty() marca https://msdn.microsoft.com/en-us/library/1hkt4325(v=vs .90) .aspx – abhaybhatia

+1

@abhaybhatia String.Equals (a, b) no considera que null sea igual a string vacío, que es lo que se deseaba. Por lo tanto, la verificación string.IsNullOrEmpty es necesaria. –

54

no elimina las comparaciones subyacentes adicionales, pero para el factor de atracción sexual, podría utilizar algo como esto:

(strA ?? "") == (strB ?? "") 

o un poco menos atractivo, pero la forma preferible:

(strA ?? string.Empty) == (strB ?? string.Empty) 
+0

Bueno, estaba tratando de evitar hacer cientos de comparaciones con un método de extensión, pero supongo que voy a tener que morder la bala. Puedo terminar escribiendo un método que realiza esto detrás de escena. Gracias. – billb

+8

+1, pero solo la parte con 'String.Empty' en ella! – user7116

+0

El 'string.Empty' no es _quite_ tan sexy (menos compacto) por lo que incluí ambos, pero sí, se prefiere' string.Empty'. – iammichael

5

¿Qué pasa con

strA ?? "" == strB ?? "" 
2

¿Qué pasa con string.IsNullOrEmpty()? Estoy seguro de que, dado que es parte del framework .NET, está optimizado y probablemente sea mucho más eficiente que algo que tú o yo podríamos escribir. Puede que no sea sexy, pero funciona. Escriba un código que sea fácil de leer y permita que el compilador clasifique los detalles.

+0

Porque hay dos controles, y ahora tengo que reemplazar cientos de comparaciones con todo este ruido. – billb

+0

Eso puede ser pero no podría encontrar un reemplazo ayudarle con la actualización del código? – TLiebe

+0

Claro, pero ¿no vas a reemplazar cientos de comparaciones de todos modos? ¿Cómo planeas hacer este reemplazo de '! =' Sin un esfuerzo manual? –

9
No

tan atractivo como ??, pero se puede evitar el doble papel comparación del tiempo si cortocircuitarla:

string.IsNullOrEmpty(strA) ? string.IsNullOrEmpty(strB) : (strA == strB) 
0

Si sus 2 conjuntos de campos están en algún tipo de colección, puede usar LINQ para su ventaja. Si están en una especie de colección que le permite acceder a ellos mediante llave y ambos tienen las mismas claves, puede utilizar esta (lista para ser pegada en LINQPad):

Dictionary<string,string> fields1 = new Dictionary<string,string>(); 
Dictionary<string,string> fields2 = new Dictionary<string,string>(); 

fields1.Add("field1", "this"); 
fields2.Add("field1", "this"); 
fields1.Add("field2", "is"); 
fields2.Add("field2", ""); 
fields1.Add("field3", "a"); 
fields2.Add("field3", null); 
fields1.Add("field4", "test"); 
fields2.Add("field4", "test"); 

var test = 
from f1 in fields1 
    join f2 in fields2 
    on f1.Key equals f2.Key 
select (f1.Value ?? "") == (f2.Value ?? ""); 

test.Dump(); 

Si usted tiene los conjuntos de campos en 2 colecciones indexadas en el mismo orden, se podrían usar algo como esto:

string[] strings1 = { "this", "is", "a", "test" }; 
string[] strings2 = { "this", "", null, "test" }; 

var test = 
from s1 in strings1.Select((value,index) => new {value, index}) 
    join s2 in strings2.Select((value,index) => new {value, index}) 
    on s1.index equals s2.index 
select (s1.value ?? "") == (s2.value ?? ""); 

test.Dump(); 
0

las soluciones de otros dieron, incluyendo el que se propone definir una clase de comparación para las cuerdas, se olvidó de escribir un nuevo GetHashCode de tus cuerdas.

Esto significa que su cadena no se puede utilizar en clases que dependen de GetHashCode como Dictionary<T> o HashSet<T>.

Ver Why is it important to override GetHashCode when Equals method is overridden?

Cada vez que se decide cambiar el concepto de la igualdad para cualquier clase, debe escribir un EqualityComparer para esa clase. Esto asegura que si de acuerdo con su definición cambiada de igualdad a los objetos se consideran iguales, su GetHashCode devolverá valores iguales.

public class NullStringComparer : EqualityComparer<string> 
{ 
    public override bool Equals(string x, string y) 
    { 
     // equal if string.Equals(x, y) 
     // or both StringIsNullOrEmpty 
     return String.Equals(x, y) 
      || (String.IsNullOrEmpty(x) && String.IsNullOrEmpty(y)); 
    } 

    public override int GetHashCode(string obj) 
    { 
     if (String.IsNullOrEmpty(obj)) 
      return 0; 
     else 
      return obj.GetHashCode(); 
    } 
} 

Uso:

public static void Main() 
{ 
    string x = null; 
    string y = String.Empty; 

    Console.WriteLine($"Standard string comparison: {StringComparer.Ordinal.Equals(x, y)}"); 

    IEqualityComparer<string> equalityComparer = new NullStringComparer(); 
    Console.WriteLine($"My string comparison {equalityComparer.Equals(x, y)}"); 

    int hashX = equalityComparer.GetHashCode(x); 
    int hashY = equalityComparer.GetHashCode(y); 
    Console.WriteLine($"hash X = {hashX}, hash Y = {hashY}"); 
} 
Cuestiones relacionadas