简体   繁体   中英

Using 'as IDisposable' in a using block

Edit: My question isn't about a using block and how it works. My question is about the difference in the two ways to do it, shown below.

I'm reading the CQRS Journey Guide, and I don't understand this line of code:

using (repo as IDisposable)

What does that mean? Why use it as IDisposable? In a typical using block, one doesn't need to use it as IDisposable:

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

Any idea why the authors wrote it the first way instead of the second way?

This is the method in which that code appears:

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;
    }
}

Any idea why the authors wrote it the first way instead of the second way?

This is often due to a misunderstanding of the language feature. The way you wrote it is the idomatic way to write it in C#:

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

The only real advantage to the author's approach would be if repositoryFactory could, potentially, return a type which doesn't implement IDisposable . By writing the code via using (repo as IDisposable) , the same code could handle non-disposable types.

Most of the time, this isn't an issue. However, it would be possible that the factory could optionally return an IDisposable type. As an example, suppose this method was done within a generic class, and repositoryFactory returned an IRepository<T> , it would be possible that type may or may not implement IDiposable , in which case this approach would handle both cases without imposing an IDisposable constraint on the generic type.

Saying using(X as IDisposable) instructs the compiler that X identifies a particular instance of a type which implements IDisposable , then the using block should guard that instance, and otherwise it should guard nothing. Such a usage would be appropriate if the return type of the method this.repositoryFactory() did not implement IDisposable , but the method would sometimes return instances of types which do implement IDisposable and expect it to be called.

Note that any type which will be used as the return type of a factory that may produce IDisposable objects needing cleanup should implement IDisposable , even if only 99.9% of the objects generated would have Dispose methods that do nothing and don't actually have to be called. The non-generic IEnumerator fits that description to a "T", and thus should have implement IDisposable , but since it doesn't the best usage pattern is probably:

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

Very similar to what is observed in the code using repositoryFactory() above.

if somewhere in the using block the code fails, or reach a point of exception. Its guaranteed that repo is beeing disposed.

Difference between the two lines is that there is no difference. cast to IDisposable is not nessecary, it is purely theorethical. possible differences

  • after the using you want to do something with repo.
  • cleaner code

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM