【问题标题】:Using 'as IDisposable' in a using block在 using 块中使用“as IDisposable”
【发布时间】:2013-11-15 21:45:50
【问题描述】:

编辑:我的问题不是关于 using 块及其工作原理。我的问题是关于这两种方法的区别,如下所示。

我在看CQRS旅程指南,这行代码看不懂:

using (repo as IDisposable)

这是什么意思?为什么将它用作 IDisposable?在典型的 using 块中,不需要将其用作 IDisposable:

using (var repo = this.respositoryFactory()) { // ... }

知道为什么作者是用第一种方式而不是第二种方式写的吗?

这是该代码出现的方法:

private Conference.Web.Public.Models.Conference GetConference(string conferenceCode)
{
    var repo = this.repositoryFactory();
    using (repo as IDisposable)
    {
        var conference = repo.Query<Conference>()
            .First(c => c.Code == conferenceCode);
        var conferenceModel =
        new Conference.Web.Public.Models.Conference
        {
            Code = conference.Code,
            Name = conference.Name,
            Description = conference.Description
        };
        return conferenceModel;
    }
}

【问题讨论】:

  • 简单,你不能在 using 块中使用任何旧类型,它必须是 IDisposable 的类型。
  • 如果实例的类没有实现IDisposableas IDisposable 如何神奇地允许释放实例?如果它已经实现了IDisposable,那为什么using 语句还不够呢?我从未见过它需要演员表。
  • @iamkrillin 如果它已经是一次性的,您不必在 using 块中设置“as IDisposable”。
  • 嗯,简短的回答,演员是没有必要的。
  • 这里有很好的解释:stackoverflow.com/questions/4695649/…

标签: c# idisposable using


【解决方案1】:

知道作者为什么用第一种方式而不是第二种方式写它吗?

这通常是由于对语言功能的误解。您编写它的方式是用 C# 编写它的惯用方式:

using (var repo = this.respositoryFactory()) 
{

作者的方法唯一真正的优势是repositoryFactory 可能返回一个不实现IDisposable 的类型。通过using (repo as IDisposable) 编写代码,相同的代码可以处理非一次性类型。

大多数时候,这不是问题。但是,工厂有可能可选地返回IDisposable 类型。例如,假设这个方法是在一个泛型类中完成的,并且repositoryFactory 返回了一个IRepository&lt;T&gt;,那么该类型可能实现也可能不实现IDiposable,在这种情况下,这种方法可以处理这两种情况而不会强加泛型类型的IDisposable 约束。

【讨论】:

  • 这不是假设repositoryFactory 返回一个实现IDisposable 的类型吗?例如,如果它返回对象怎么办?
  • @CodeNaked repositoryFactory 必须返回 IDisposable 否则无法编译。
  • @BobHorn - 是的,但如果它是一个可能实现也可能不实现 IDisposable 的类型,“工厂”可能就是这种情况,那么您需要将其转换为IDisposable。这似乎不适用于这种特殊情况,但您没有显示 repositoryFactory 的类型定义。
  • @CodeNaked:如果工厂的返回类型肯定不符合IDisposable,则会引发编译器错误。它必须返回 IDisposable 或实现它的类/接口。
  • @CodeNaked:如果你说using m=this.repositoryFactory() as IDisposable,那么如果repositoryFactory()返回的对象没有实现IDisposablem将为空。在最初编写的代码中,repo 将持有对未实现 IDisposable 的对象的引用,而 using 块将完美地保护 null
【解决方案2】:

using(X as IDisposable) 指示编译器X 标识了实现IDisposable 的类型的特定instance,然后using 块应该保护该实例,否则它不应该保护任何东西。如果方法this.repositoryFactory() 的返回类型没有实现IDisposable,则这种用法是合适的,但该方法有时会返回实现IDisposable 的类型的实例并期望它被调用。

请注意,任何将用作工厂的返回类型的类型,该工厂可能会产生需要清理的 IDisposable 对象,但应实现 IDisposable,即使生成的对象中只有 99.9% 具有 Dispose 方法什么都没有,实际上不必调用。非泛型 IEnumerator 适合该描述为“T”,因此应该实现 IDisposable,但由于它不是最佳使用模式可能是:

IEnumerator enumerator = myEnumerable.GetEnumerator();
using (enumerator as IDisposable)
{
  ...
}

与上面使用repositoryFactory() 的代码中观察到的非常相似。

【讨论】:

    【解决方案3】:

    如果在 using 块中的某个地方代码失败,或者到达异常点。它保证回购被处理。

    这两条线的区别在于没有区别。强制转换为 IDisposable 不是必需的,它纯粹是理论上的。可能的差异

    • 使用后你想用 repo 做点什么。
    • 更简洁的代码

    【讨论】:

    • 我明白了。两种方法都不是这样吗?两者有什么区别?
    • 如果DepositoryFactory 的返回类型没有实现IDisposable,但该方法有时可能会生成确实 实现IDisposable 的类型实例,因此需要清理,as IDisposable 将是必需的。
    猜你喜欢
    • 2018-04-04
    • 2011-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多