2010-03-10 26 views
128

Algo que me parece hacer cada vez más es comprobar una cadena vacía (como en "" o nulo) y un operador condicional.?? ¿Se unen para una cadena vacía?

Un ejemplo actual:

s.SiteNumber.IsNullOrEmpty() ? "No Number" : s.SiteNumber; 

Esto es sólo un método de extensión, que es equivalente a:

string.IsNullOrEmpty(s.SiteNumber) ? "No Number" : s.SiteNumber; 

Ya que es vacío y no nula, ?? no va a hacer el truco. Una versión string.IsNullOrEmpty() de ?? sería la solución perfecta. Estoy pensando que tiene que haber una manera más limpia de hacerlo (¡espero!), Pero no he podido encontrarlo.

¿Alguien sabe de una mejor manera de hacer esto, incluso si solo está en .NET 4.0?

+8

Para tentarlo un poco, puede definir fácilmente los operadores binarios personalizados y ad-hoc (para el caso) en F #.Aquí 'let (|?) X y = if String.IsNullOrEmpty (x) then y else x' y úselo como' s.SiteNumber |? "Sin número" '. –

+0

Espero que no te importe la edición. – gdoron

Respuesta

61

No hay una forma integrada de hacerlo. Sin embargo, podría hacer que su método de extensión devuelva una cadena o nulo, lo que permitiría que el operador coalescente funcione. Sin embargo, esto sería extraño, y yo personalmente prefiero su enfoque actual.

Puesto que ya está utilizando un método de extensión, ¿por qué no hacer uno que devuelve el valor o un defecto:

string result = s.SiteNumber.ConvertNullOrEmptyTo("No Number"); 
+6

Creo que tiene razón, y esta es la solución más limpia actualmente disponible que todavía es legible. Aunque me encantaría algo como un operador '???' en C# 5, quién sabe. –

+2

y ¿cuál sería el ??? operador hacer? tomar valores predeterminados además de nulos? Suena extremadamente complicado en el mejor de los casos – bevacqua

+1

¿Con expresiones lambda quizás? Por ejemplo: asumir que "elemento" es anulable, entonces ... 'item ?? x => x.ToString(): null; ' –

100

C# ya nos permite valores de sustitución para null con ??. Así que todo lo que necesitamos es una extensión que convierte una cadena vacía a null, y luego utilizar de esta manera:

s.SiteNumber.NullIfEmpty() ?? "No Number"; 
3

¿qué tal un método de extensión de cadena ValueOrDefault()

public static string ValueOrDefault(this string s, string sDefault) 
{ 
    if (string.IsNullOrEmpty(s)) 
     return sDefault; 
    return s; 
} 

o devolver un valor nulo si la cadena está vacía:

public static string Value(this string s) 
{ 
    if (string.IsNullOrEmpty(s)) 
     return null; 
    return s; 
} 

No intenté estas soluciones.

+2

Me gusta la opción n. ° 1, aunque la llamaría algo más semántica como O(), así que podría escribir "string s = s.SiteNumber.Or (" Default ");" – jvenema

+2

Llamar a algo '... OrDefault()' sería confuso si no se comportara como el resto de los métodos '... OrDefault()' del framework. Nos guste o no, MS ha dado un significado específico a esa denominación y la desviación de ese comportamiento en los métodos personalizados es innecesariamente confusa para los usuarios de su API. – mattmc3

28

Sé que esto es una vieja pregunta - pero yo estaba buscando una respuesta y nada de lo anterior se ajusta a mi necesidad, así como lo que terminé usando:

private static string Coalesce(params string[] strings) 
{ 
    return strings.FirstOrDefault(s => !string.IsNullOrEmpty(s)); 
} 

Uso:

string result = Coalesce(s.SiteNumber, s.AltSiteNumber, "No Number"); 

EDIT: Una forma aún más compacta de escribir esta función sería:

static string Coalesce(params string[] strings) => strings.FirstOrDefault(s => !string.IsNullOrEmpty(s)); 
+1

Me gusta, pero tuve que corregir un error del compilador y hacerlo un poco más compacto. – gregmac

+0

¿Por qué llama a esto Coalesce cuando no une los valores, sino que simplemente selecciona el que no está vacío? Es un nombre confuso amigo. – Jimmyt1988

+0

Porque Coalesce es el término usado por muchas bases de datos para hacer la misma operación (encontrar el primer valor no nulo). Unir cadenas es concatenación. –

13

Tengo un par de extensiones de utilidad que me gusta usar:

public static string OrDefault(this string str, string @default = default(string)) 
{ 
    return string.IsNullOrEmpty(str) ? @default : str; 
} 

public static object OrDefault(this string str, object @default) 
{ 
    return string.IsNullOrEmpty(str) ? @default : str; 
} 

Editar: Inspirado en respuesta SFSR 's, voy a añadir esta variante a mi caja de herramientas a partir de ahora:

public static string Coalesce(this string str, params string[] strings) 
{ 
    return (new[] {str}) 
     .Concat(strings) 
     .FirstOrDefault(s => !string.IsNullOrEmpty(s)); 
} 
+0

Definitivamente estoy usando el término "Coalesce", ya que se parece más a la intención del operador nulo coalescente (??), aunque lo cambié a "CoalesceTo". – llaughlin

+0

¿Qué hace el prefijo '@' en el parámetro '@ default'? Nunca había visto eso antes. –

+1

@druciferre - Eso solo le permite usar 'default' como un nombre de variable a pesar de que es una palabra clave reservada en C#. –

6

un método ligeramente más rápido que el propuesto anteriormente extensión quizá:

public static string Fallback(this string @this, string @default = "") 
{ 
    return (@this == null || @this.Trim().Length == 0) ? @default : @this; 
} 
+11

¿Por qué no hacer uso de [IsNullOrWhitespace] (http://msdn.microsoft.com/en-us/library/system.string.isnullorwhitespace.aspx) en lugar de recortarlo y medirlo? – weston

+1

'código' cadena pública pública Coalesce (esta cadena @this, cadena @default =" ") { return (@this == null || String.IsNullOrWhiteSpace (@this))? @default: @this; } –

2

estoy usando una cadena ext Coalesce método de decisión propio. Desde aquí los están usando LINQ, y absolutamente impresionante derroche de recursos para las operaciones intensivas de tiempo (lo estoy usando en los bucles), voy a compartir la mía:

public static class StringCoalesceExtension 
{ 
    public static string Coalesce(this string s1, string s2) 
    { 
     return string.IsNullOrWhiteSpace(s1) ? s2 : s1; 
    } 
} 

Creo que es bastante simple, y usted don' Incluso necesita molestarse con los valores de cadena nula. Úselo así:

string s1 = null; 
string s2 = ""; 
string s3 = "loudenvier"; 
string s = s1.Coalesce(s2.Coalesce(s3)); 
Assert.AreEqual("loudenvier", s); 

Lo uso mucho. Una de esas funciones de "utilidad" que no puede vivir sin utilizarla por primera vez :-)

0

Me gusta la brevedad del siguiente método de extensión QQQ para esto, aunque por supuesto un operador como? seria mejor. Pero podemos aumentar esto al permitir que se comparen no solo dos sino tres valores de opción de cadena, con lo que uno debe enfrentarse cada tanto (consulte la segunda función a continuación).

#region QQ 

[DebuggerStepThrough] 
public static string QQQ(this string str, string value2) 
{ 
    return (str != null && str.Length > 0) 
     ? str 
     : value2; 
} 

[DebuggerStepThrough] 
public static string QQQ(this string str, string value2, string value3) 
{ 
    return (str != null && str.Length > 0) 
     ? str 
     : (value2 != null && value2.Length > 0) 
      ? value2 
      : value3; 
} 


// Following is only two QQ, just checks null, but allows more than 1 string unlike ?? can do: 

[DebuggerStepThrough] 
public static string QQ(this string str, string value2, string value3) 
{ 
    return (str != null) 
     ? str 
     : (value2 != null) 
      ? value2 
      : value3; 
} 

#endregion 
2

Una de las ventajas del operador de fusión nula es que provoca cortocircuitos. Cuando la primera parte no es nula, la segunda parte no se evalúa. Esto puede ser útil cuando la alternativa requiere una operación costosa.

terminé con:

public static string Coalesce(this string s, Func<string> func) 
{ 
    return String.IsNullOrEmpty(s) ? func() : s; 
} 

Uso:

string navigationTitle = model?.NavigationTitle. 
    Coalesce(() => RemoteTitleLookup(model?.ID)). // Expensive! 
    Coalesce(() => model?.DisplayName); 
0

simplemente utilizan un método de extensión NullIfEmpty que siempre devolverá NULL si la cadena está vacía permitiendo ?? (Operador coalescente nulo) para ser utilizado como normal.

public static string NullIfEmpty(this string s) 
{ 
    return s.IsNullOrEmpty() ? null : s; 
} 

Esto luego permite? para ser utilizado como normal y hace que el encadenamiento sea fácil de leer.

string string1 = string2.NullIfEmpty() ?? string3.NullIfEmpty() ?? string4; 
Cuestiones relacionadas