【问题标题】:using statement with array - type must be implicitly convertible to 'System.IDisposable'using 语句与数组 - 类型必须隐式转换为 'System.IDisposable'
【发布时间】:2018-02-23 12:12:44
【问题描述】:

使用using 语句的以下代码旨在避免某种内存泄漏,这会导致代码在长文件中变慢:

var db = new EntityContext();
var cubos = db.CubosTrabalhados;
var cubo = new CuboTrabalhado();
string[] lines = File.ReadAllLines(Files.cuboHistorico, Encoding.Default);
bool header = true;
int i = 2;

foreach (string line in lines)
{
    if (header) header = false;
    else
    {
        using (var reg = line.Split(';'))
        {
            cubo.Pedido = reg[0];
            cubo.DataPedido = Select.ParseDate(reg[3]);
            cubo.Cliente = reg[4];
            cubo.UF = Select.Uf(reg[5]);
            cubo.Cidade = reg[6];
            cubo.Regiao = reg[7];
            cubo.Codigo = reg[8];
            cubo.Produto = reg[9];
            ...
            cubo.VlCom = Select.ParseFloat(reg[63]);
            cubo.Cnpj = reg[64];
            cubo.CodProdOriginal = reg[65];

            cubos.Add(cubo);
            db.SaveChanges(); 
        }
    }
}

但是带有using 语句的行给出了错误:

'string[]': 在 using 语句中使用的类型必须是隐式的 可转换为“System.IDisposable”

由于Split 是.net 的常规部分,我不知道在这种情况下如何实现IDisposable 接口。

它是如何工作的?

【问题讨论】:

  • 只需删除using,除非您在某处保存对reg 的引用,否则拆分字符串不会导致内存泄漏。
  • 您不需要处理字符串数组。这就是垃圾收集器的工作
  • using 在这种情况下完全没用。
  • 在这种情况下需要处理的是 DbContext,而不是字符串数组。
  • 这很慢,因为您正在为每一行写入数据库。将您的数据库保存更改放在每个循环之外。您已经跟踪了cubos

标签: c# asp.net .net arrays


【解决方案1】:

Split 返回一个Array,它没有实现IDisposable。在这种情况下你不能使用using,更重要的是 - 你不需要。

【讨论】:

    【解决方案2】:

    您只能对实现IDisposable 的类型使用using 语句。 string[] 没有实现它,因为字符串是托管资源,所以垃圾收集器会清理所有内容。

    • 因此,如果您尝试与数组一起使用,则没有必要并且不会编译。但是你应该总是处理EntityContext,它真正实现了IDisposable
    • 还有一个错误。您只有一个 CuboTrabalhado 实例,因为您在循环之前声明它,您希望为 string[] 中的每个项目创建一个。
    • 你可以在循环之后调用SaveChanges来提交所有更改,你不需要在里面做

    using(var db = new EntityContext())
    {
        var cubos = db.CubosTrabalhados;
        string[] lines = File.ReadAllLines(Files.cuboHistorico, Encoding.Default);
        bool header = true;
        int i = 2;
    
        foreach (string line in lines)
        {
            if (header) header = false;
            else
            {
                var reg = line.Split(';');
                var cubo = new CuboTrabalhado();
                cubo.Pedido = reg[0];
    
                ...
    
                cubos.Add(cubo);
            }
        }
        db.SaveChanges(); 
    }
    

    【讨论】:

      【解决方案3】:

      using 语句是IDisposable 接口和模式的执行部分。您的错误来自string[] 不是传统意义上的类,更不用说继承自IDisposable 的类了。

      using 不会神奇地防止内存泄漏。它阻止它们的方式是它如何作为语法糖发挥作用,使代码在使用具有非托管资源的IDisposable 对象时更易于阅读和维护。一个例子是SqlCommand

      using(var x = new SqlCommand("select gunk from someStuff", myDataConnection))
      {
              x.Connection.Open();
              x.ExecuteQuery();
      }
      

      一样
      var x = new SqlCommand("select gunk from someStuff", myDataConnection);
      try
      {
             x.Connection.Open();
             x.ExecuteQuery();
      }
      finally
      {
            x.Connection.Close();
            x.Dispose(); 
      }
      

      如您所见,using 大部分都在那里,因此您不必记住关闭/处置连接或对象,并在大块代码中使其范围更加清晰。

      您的性能缓慢可能是因为您在循环中敲击SaveChanges()。在完成更改而不是在每次迭代期间调用该方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多