c# - vacios - subconjunto
¿Un conjunto vacío en.NET utiliza algún espacio? (8)
Esta no es una respuesta directa a tu pregunta.
Lea por qué las matrices se consideran algo dañinas . Le sugiero que devuelva un <string> IList en este caso y que reestructure un poco el código:
IList<string> GetTheStuff() {
List<string> s = new List<string>();
if( somePredicate() ) {
// imagine we load some data or something
}
return s;
}
De esta forma, la persona que llama no tiene que preocuparse por los valores de retorno vacíos.
EDITAR : Si la lista devuelta no debe ser editable, puede envolver la Lista dentro de ReadOnlyCollection . Simplemente cambie la última línea a. También consideraría esta mejor práctica.
return new ReadOnlyCollection(s);
Tengo un código donde estoy devolviendo una matriz de objetos.
Aquí hay un ejemplo simplificado:
string[] GetTheStuff() {
List<string> s = null;
if( somePredicate() ) {
s = new List<string>(); // imagine we load some data or something
}
return (s == null) ?
new string[0] :
s.ToArray();
}
La pregunta es, ¿qué tan caro es el new string[0]
?
¿Debería devolver nulo y hacer que la persona que llama acepte nulo como una forma válida de indicar "no se encontró nada"?
NB: Esto se llama en un ciclo que se ejecuta cientos y cientos de veces, por lo que es uno de los pocos casos en los que creo que este tipo de optimización no es en realidad ''prematuro''.
PD: Y aunque fuera prematuro, me gustaría saber cómo funciona :-)
Actualizar:
Inicialmente cuando le pregunté si usaba algún espacio, estaba pensando en cosas desde el punto de vista ''C / C ++'', algo así como cómo en C, escribir char a[5];
asignará 5 bytes de espacio en la pila, y char b[0];
asignará 0 bytes.
Me doy cuenta de que esto no es una buena opción para el mundo .NET, pero tenía curiosidad si esto era algo que el compilador o CLR detectaría y optimizaría, ya que una matriz no redimensionable de tamaño cero realmente no debería (hasta donde Puedo ver?) Requieren espacio de almacenamiento.
Incluso si se llama "cientos y cientos" de veces, diría que es una optimización prematura. Si el resultado es más claro como una matriz vacía, úselo.
Ahora para la respuesta real: sí, una matriz vacía requiere algo de memoria. Tiene la sobrecarga normal del objeto (8 bytes en x86, creo) y 4 bytes para el recuento. No sé si hay algo más allá de eso, pero no es completamente gratis. (Aunque es increíblemente barato ...)
Afortunadamente, hay una optimización que puede realizar sin comprometer la API en sí: tiene una "constante" de una matriz vacía. He hecho otro pequeño cambio para aclarar el código, si me permite ...
private static readonly string[] EmptyStringArray = new string[0];
string[] GetTheStuff() {
if( somePredicate() ) {
List<string> s = new List<string>();
// imagine we load some data or something
return s.ToArray();
} else {
return EmptyStringArray;
}
}
Si encuentra que necesita esto con frecuencia, incluso podría crear una clase genérica con un miembro estático para devolver una matriz vacía del tipo correcto. La manera en que el trabajo de genéricos de .NET hace esto trivial:
public static class Arrays<T> {
public static readonly Empty = new T[0];
}
(Podría envolverlo en una propiedad, por supuesto).
Entonces solo usa: Arrays <string> .Empty;
EDITAR: Acabo de recordar la publicación de Eric Lippert en arreglos . ¿Estás seguro de que una matriz es el tipo más apropiado para devolver?
Las matrices declaradas siempre deberán contener la siguiente información:
- Rango (cantidad de dimensiones)
- Tipo para ser contenido
- Longitud de cada dimensión
Esto probablemente sea trivial, pero para números más grandes de dimensiones y longitudes más altas tendrá un impacto en el rendimiento de los bucles.
En cuanto a los tipos de devolución, acepto que se devuelva un conjunto vacío en lugar de nulo.
Más información aquí: Tipos de matrices en .NET
Sí, como han dicho otros, la matriz vacía ocupa unos pocos bytes para el encabezado del objeto y el campo de longitud.
Pero si te preocupa el rendimiento, te estás enfocando en la rama incorrecta de ejecución en este método. Estaría mucho más preocupado acerca de la llamada ToArray en la lista poblada que dará como resultado una asignación de memoria igual a su tamaño interno y una copia de memoria de los contenidos de la lista en ella.
Si realmente desea mejorar el rendimiento, luego (si es posible) devuelva la lista directamente haciendo que el retorno escriba uno de los siguientes: List<T>, IList<T>, ICollection<T>, IEnumerable<T>
dependiendo de qué servicios necesita de (tenga en cuenta que menos específico es mejor en el caso general).
Si entiendo correctamente, se asignará una pequeña cantidad de memoria para las matrices de cadenas. Su código esencialmente requiere una lista genérica para ser creada de todos modos, entonces ¿por qué no solo devolver eso?
[EDIT] Eliminó la versión del código que devolvió un valor nulo. Las otras respuestas que aconsejan no tener valores de retorno nulos en esta circunstancia parecen ser el mejor consejo [/ EDIT]
List<string> GetTheStuff()
{
List<string> s = new List<string();
if (somePredicarte())
{
// more code
}
return s;
}
Supongo que una matriz vacía usa solo el espacio necesario para asignar el puntero del objeto.
Desde la memoria, las directrices de la API dicen que siempre debe devolver una matriz vacía de un método que devuelve una matriz en lugar de devolver nulo, por lo que dejaría su código tal como está. De esa forma, la persona que llama sabe que tiene garantizado obtener una matriz (incluso una vacía) y no necesita verificar el nulo con cada llamada.
Editar: un enlace sobre cómo devolver matrices vacías:
http://wesnerm.blogs.com/net_undocumented/2004/02/empty_arrays.html
Otros han respondido a su pregunta muy bien. Así que solo un punto simple para hacer ...
Evitaría devolver una matriz (a menos que no puedas). Quédese con IEnumerable y luego puede usar Enumerable.Empty<T>()
desde las API de LINQ. Obviamente, Microsoft ha optimizado este escenario para usted.
IEnumerable<string> GetTheStuff()
{
List<string> s = null;
if (somePredicate())
{
var stuff = new List<string>();
// load data
return stuff;
}
return Enumerable.Empty<string>();
}
La próxima versión 4.6 de .NET (más adelante en 2015) contiene un método estático que devuelve una string[]
longitud cero string[]
:
Array.Empty<string>()
Supongo que devuelve la misma instancia si se llama muchas veces.