Is it a good idea to have a class member that holds a resource for the whole object lifetime?

StackOverflow https://stackoverflow.com/questions/21186253

  •  29-09-2022
  •  | 
  •  

I could have a class that has a member that holds a resource or at least it implements IDisposable. Here is one example (just for showing what I mean):

public class Something
{
    private HMACSHA1 HmacSha1;

    public Something()
    {
        HmacSha1 = new HMACSHA1();
    }

    public byte[] DoIt(byte[] bytes)
    {
        return HmacSha1.ComputeHash(bytes);
    }
}

The member HmacSha1 implements IDisposable and should therefore be disposed at the end of the object's lifetime. I know that and it's not part of my question and intentionally left out in the example. Also it could be of any other type holding a resource, like a database or network connection.

I want to know whether it is a good idea to keep that member open (I mean created once in the beginning and not disposed) for the whole lifetime of the object?

Or would it be better to create and dispose it where it is needed - in method DoIt() in the above example?

What are the downsides?

有帮助吗?

解决方案

I think this really depends on what the object is and how you are using it.

Constructing it once and holding onto it may make sense if the object contains state information that is not convenient to store elsewhere that you need to persist.

It may also make sense for performance reasons if the object's methods are quick to execute but the object is expensive to create and free. If its methods are in a performance bottleneck then it would provide a performance advantage to keep the object alive and remove construction/destruction overhead from those time-sensitive method calls.

Consider :

public Something()
{
    someObject = new SomeObject();  //let's say this takes 350ms
}

public byte[] DoIt(byte[] bytes)
{
    return someObject.ComputeHash(bytes);  //let's say this takes 3ms
}

now...

private void doSomething()
{
    for(int i = 0; i < 100000; i++) { 
      someList.Add(something.DoIt(someBytes)); //this will take 5 minutes
    }  // but if someObject is created and freed in the loop it will take
}      // almost ten hours!

The argument for dynamically creating and freeing it work in pretty much the same way. If the object is large and consumes a lot of memory it may be more efficient to have it alive only when needed (if it does not contain any state information that cannot be efficiently preserved elsewhere) so long as the performance penalty for dynamically creating and freeing the object is small compared to the gains in memory footprint.

Imagine that the use case for class Something will involve hundreds of instances of it being alive at any given time. If they all keep a persistent instance of someObject that is infrequently used then you have a hundreds of times its memory footprint alive at once while each individual Something may only need it once in a while. In this case it's much better to only create it if you need it.

As a rule, then, I suppose it's best to say that any object, struct, or variable should probably only persist as long as there is a reason for it to persist. If you can't make a sensible argument to keep it around then free it up.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top