code

리소스가없는 클래스에서 IDisposable을 구현하면 어떤 이점이 있습니까?

codestyles 2020. 12. 8. 08:05
반응형

리소스가없는 클래스에서 IDisposable을 구현하면 어떤 이점이 있습니까?


C #에서 관리자 클래스와 같은 클래스에 리소스가없는 경우이를 갖는 이점이 : IDisposable있습니까?

간단한 예 :

public interface IBoxManager
{
 int addBox(Box b);
}

public class BoxManager : IBoxManager
{
 public int addBox(Box b)
 {
  using(dataContext db = new dataContext()){
   db.Boxes.add(b);
   db.SaveChanges();
  }
  return b.id;
 }
}

IDisposable도 구현하는 경우 BoxManager를 사용할 때 메모리 사용에 이점이 있습니까? public class BoxManager : IBoxManager , IDisposable

예를 들면 :

BoxManager bm = new BoxManager();
bm.add(myBox);
bm.dispose();//is there benefit to doing this?

IDisposable유형 에 구현 하는 이유는 두 가지뿐입니다.

  • 유형에는 유형이 더 이상 사용되지 않을 때 해제되어야하는 원시 자원이 포함됩니다.
  • 유형에는 유형의 필드가 포함됩니다. IDisposable

둘 다 사실이 아니면 구현하지 마십시오. IDisposable

편집하다

여러 사람들이 IDisposable시작 / 종료 또는 예약 된 작업을 구현하는 좋은 방법 이라고 언급했습니다 . IDisposable그것이 원래 의도는 아니지만 아주 좋은 패턴을 제공합니다.

class Operation {
  class Helper : IDisposable {
    internal Operation Operation;
    public void Dispose() {
      Operation.EndOperation();
    }
  }
  public IDisposable BeginOperation() {
    ...
    return new Helper() { Operation = this };
  }
  private void EndOperation() {
    ...
  }
}

참고 :이 패턴을 구현하는 또 다른 흥미로운 방법은 람다를 사용하는 것입니다. IDisposable사용자 에게 돌려 주고 호출하는 것을 잊지 않기를 바라는 대신 Dispose작업을 실행할 수있는 람다를 제공하고 작업을 종료합니다.

public void BeginOperation(Action action) {
  BeginOperationCore();
  try {
    action();
  } finally {
    EndOperation();
  }
}

방법을 명시 적으로 사용하지 않으면 일회용 버전과 일회용 버전간에 차이가 없습니다 Dispose().


귀하의 코드는 IDisposable을 구현해도 이익을 얻지 못하지만 IDisposable은 (직간접 적으로) 네이티브 리소스를 무료로 사용하기위한 것이라는 다른 의견에 동의 할 수 없습니다. IDisposable은 개체가 수명 기간이 끝날 때 정리 작업을 수행해야 할 때마다 사용할 수 있습니다. 와 함께 매우 유용합니다 using.

매우 인기있는 예 : ASP.NET에서 MVC Html.BeginForm는 IDisposable을 반환합니다. 생성시 개체는 태그를 열고 Dispose가 호출되면 태그를 닫습니다. 관련된 기본 리소스는 없지만 여전히 IDisposable을 잘 사용합니다.


아니요, 클래스가 Dispose메서드에 포함 할 수있는 관리되지 않는 리소스를 해제하는 것과 같은 유용한 작업을 수행하지 않으면 이점이 없습니다 .


귀하의 경우에는 적용 할 수 없지만 자주 발생하는 한 가지 주요 혼란 지점은 정확히 "자원"을 구성하는 것입니다. 객체의 관점에서 볼 때 관리되지 않는 자원은 외부 엔티티 ( )가 자신을 대신하여 "행동"( *)하는 것입니다. 외부 엔티티는 중지하라는 지시가있을 때까지 다른 엔티티에 해를 끼칠 수 있습니다. . 예를 들어 개체가 파일을 여는 경우 파일을 호스팅하는 컴퓨터는 해당 개체에 단독 액세스 권한을 부여하여 더 이상 단독 액세스가 필요하지 않다는 알림을 받기 전까지는 유니버스의 다른 모든 사용자에게 해당 개체를 사용할 기회를 거부 할 수 있습니다.

(*) 어디에서나 무엇이든 될 수 있습니다. 같은 컴퓨터에 있지 않을 수도 있습니다.

(**) 또는 외부 엔티티의 행동이나 상태가 변경되는 방식

외부 엔티티가 객체를 대신하여 어떤 일을하고있는 경우 해당 서비스가 더 이상 필요하지 않다는 사실을 먼저 알리지 않고 사라지고 사라지는 경우, 외부 엔티티는 해당 객체를 대신하여 작업을 중지해야한다는 것을 알 방법이 없습니다. 더 이상 존재하지 않습니다. IDisposable은 서비스가 필요하지 않을 때 개체에 알리는 표준 수단을 제공하여 이러한 문제를 방지하는 한 가지 방법을 제공합니다. 서비스가 더 이상 필요하지 않은 개체는 일반적으로 다른 개체에게 더 이상의 호의를 요청할 필요가 없으므로 자신을 대신해 온 개체가 그렇게하는 것을 중지하도록 요청할 수 있습니다.

To allow for the case where an object gets abandoned without IDisposable.Dispose() having been called first, the system allows objects to register a "failsafe" cleanup method called Finalize(). Because for whatever reason, the creators of C# don't like the term Finalize(), the language requires the use of a construct called a "destructor" which does much the same thing. Note that in general, Finalize() will mask rather than solve problems, and can create problems of its own, so it should be used with extreme caution if at all.

A "managed resource" is typically a name given to an object which implements IDisposable and usually, though not always, implements a finalizer.


No, if there are no (managed or unmanaged) resources there is no need for IDisposable either.

Small caveat: some people use IDisposable to clean up eventhandlers or large memory buffers but

  • you don't seem to use those
  • it's a questionable pattern anyway.

From my personal experience (confirmed with discussion and other posts here) I would say, that there could be a situations where your object use massive amount of events, or not massive amount but frequent subscriptions and unsubscription from the event which sometimes leads to that the object is not garbage collected. In this case I in Dispose unsubscribe from all events my object subscribed before.

Hope this helps.


IDisposable is also great if you want to benefit the using () {} syntax.

In a WPF project with ViewModels, I wanted to be able to temporarily disable NotifyPropertyChange events from raising. To be sure other developers will re-enable notifications, I wrote a bit of code to be able to write something like:

using (this.PreventNotifyPropertyChanges()) {
    // in this block NotifyPropertyChanged won't be called when changing a property value
}

The syntax looks okay and is easily readable. For it to work, there's a bit of code to write. You will need a simple Disposable object and counter.

public class MyViewModel {
    private volatile int notifyPropertylocks = 0; // number of locks

    protected void NotifyPropertyChanged(string propertyName) {
        if (this.notifyPropertylocks == 0) { // check the counter
            this.NotifyPropertyChanged(...);
        }
    }

    protected IDisposable PreventNotifyPropertyChanges() {
        return new PropertyChangeLock(this);
    }

    public class PropertyChangeLock : IDisposable {
        MyViewModel vm;

        // creating this object will increment the lock counter
        public PropertyChangeLock(MyViewModel vm) {
            this.vm = vm;
            this.vm.notifyPropertylocks += 1;
        }

        // disposing this object will decrement the lock counter
        public void Dispose() {
            if (this.vm != null) {
                this.vm.notifyPropertylocks -= 1;
                this.vm = null;
            }
        }
    }
}

There are no resources to dispose here. I wanted a clean code with a kind of try/finally syntax. The using keyword looks better.


is there any benefit to having it : IDisposable?

It doesn't look so in your specific example, however: there is one good reason to implement IDisposable even if you don’t have any IDisposable fields: your descendants might.

This is one of the big architectural problems of IDisposable highlighted in IDisposable: What your mother never told you about resource deallocation. Basically, unless your class is sealed you need to decide whether your descendants are likely to have IDisposable members. And this isn't something you can realistically predict.

So, if your descendants are likely to have IDisposable members, that might be a good reason to implement IDisposable in the base class.


Short answer would be no. However, you can smartly use the nature of the Dispose() executement at the end of the object lifecycle. One have already gave a nice MVC example (Html.BeginForm)

I would like to point out one important aspect of IDisposable and using() {} statement. At the end of the Using statement Dispose() method is automatically called on the using context object (it must have implemented IDisposable interface, of course).


There one more reason that no one mentioned (though it's debateful if it really worth it): The convension says that if someone uses a class that implement IDisposable, it must call its Dispose method (either explicitly or via the 'using' statement). But what happens if V1 of a class (in your public API) didn't need IDisposable, but V2 does? Technically it doesn't break backward compatibility to add an interface to a class, but because of that convension, it is! Because old clients of your code won't call its Dispose method and may cause resources to not get freed. The (almost) only way to avoid it is to implement IDisposable in any case you suspect that you'll need it in the future, to make sure that your clients always call your Dispose method, that some day may be really needed. The other (and probably better) way is to implemet the lambda pattern mentioned by JaredPar above in the V2 of the API.

참고URL : https://stackoverflow.com/questions/9472304/is-there-any-benefit-to-implementing-idisposable-on-classes-which-do-not-have-re

반응형