Estoy tratando de obtener una matriz de bytes de mi modelo para ponerlo en el archivo. Tengo un método como tal:
public static byte[] GetByteArray(List<MyModel> models) { using var ms = new MemoryStream(); using var sw = new StreamWriter(ms); foreach (var model in models) { sw.Write(model.Id + "," + model.Name); sw.WriteLine(); } sw.Dispose(); return ms.ToArray(); } Este método funciona bien, pero como puede pensar, no necesito desechar StreamWriter manualmente, porque tengo una declaración de uso. Yo también lo pensé, pero cuando sw.Dispose(); el ms.ToArray(); devuelve una matriz vacía. ¿Alguien puede explicarme este comportamiento?
Tienes la línea:
using var sw = new StreamWriter(ms); Esto solo elimina el StreamWriter al final del método. Sin embargo, está llamando a ms.ToArray() antes del final del método. Esto significa que está llamando a ms.ToArray() antes de que se StreamWriter .
Sin embargo, StreamWriter está almacenando en búfer algunos datos internamente y solo los vacía a MemoryStream cuando se desechan. Por lo tanto, debe asegurarse de desechar StreamWriter antes de llamar a ms.ToArray() .
Probablemente sea más claro using la sintaxis de uso más antigua, que es explícita sobre cuándo ocurre la eliminación:
public static byte[] GetByteArray(List<MyModel> models) { using var ms = new MemoryStream(); using (var sw = new StreamWriter(ms)) { foreach (var model in models) { sw.Write(model.Id + "," + model.Name); sw.WriteLine(); } } return ms.ToArray(); }La disposición hace parte del trabajo. Enrojece al escritor. Utilice Flush() para descargarlo manualmente.
public static byte[] GetByteArray(List<MyModel> models) { var ms = new MemoryStream(); using var sw = new StreamWriter(ms); foreach (var model in models) { sw.Write(model.Id + "," + model.Name); sw.WriteLine(); } // flush the writer, to make sure it is written to the stream. sw.Flush(); return ms.ToArray(); }No es necesario que elimine el flujo de memoria, ya que StreamWriter se hace cargo.
No me gusta la construcción de que el streamwriter se apropia del flujo de memoria. Esto probablemente se deba a que el streamwriter también se puede usar directamente en un archivo. Un constructor que tiene una ruta de archivo como parámetro. (por lo que no se necesita ningún parámetro de flujo)
Si escribe elementos List<MyModel> como cadenas, puede simplificar la conversión de la siguiente manera:
public static byte[] GetByteArray(List<MyModel> models) => Encoding.UTF8.GetBytes(string.Join(Environment.NewLine, models.Select(model => $"{model.Id},{model.Name}")));O use serializadores de terceros, como Newtonsoft.Json (ejemplo de aquí ):
public static byte[] Serialize<T>(this T source) { var asString = JsonConvert.SerializeObject(source, SerializerSettings); return Encoding.Unicode.GetBytes(asString); } public static T Deserialize<T>(this byte[] source) { var asString = Encoding.Unicode.GetString(source); return JsonConvert.DeserializeObject<T>(asString); }