Skip to content

[API Proposal]: Consider adding a Clone() Method to the hash implementations #111908

Closed
@markusschaber

Description

@markusschaber

Background and motivation

Our (rather old) home-grown CRC32 implementation has a Clone() method, which clones the internal state of the CRC32 into a new instance, which is then usable independently of the original instance.

It is used in several places in our existing Software, for rather weird backwards compatibility reasons with existing protocols and file formats, so in those cases, we cannot migrate to the System.IO.Hashing package and benefit from the performance optimizations (ARM intrinsics, Vectorization etc.).

Implementing Clone should be easy and straight forward (just create a new instance and copy the state over). Below, I'll specify it for CRC32, but it can be easily expanded to all algorithms.

If you're interested, I could try to work out a fully-fledged pull request.

API Proposal

namespace System.IO.Hashing;

public sealed partial class Crc32
{
    /// <summary> Returns a clone of the current instance, with a copy of the internal state. </summary>
    public Crc32 Clone();
}

public sealed partial class Crc64
{
    public Crc64 Clone();
}

public sealed partial class XxHash3
{
    public XxHash3 Clone();
}

public sealed partial class XxHash32
{
    public XxHash32 Clone();
}

public sealed partial class XxHash64
{
    public XxHash64 Clone();
}

public sealed partial class XxHash128
{
    public XxHash128 Clone();
}

API Usage

// Fancy the value
var crc = new Crc32();
crc.Append(SomeCommonData);

var clone = crc.Clone();

crc.Append(SomeDataVariantA);
var aSum = crc.GetCurrentHashAsUint32();

clone.Append(SomeDataVariantB);
var bSum = clone.GetCurrentHashAsUnit32();

Alternative Designs

We could implement the ICloneable interface. The advantage is that we implement a standard interface. The disadvantage is that ICloneable.Clone() returns object, requiring an additional cast before the cloned instance can be used. To remedy this, the ICloneable interface could be implemented explicitly, in addition to the typed Clone() method shown above, so we can have the best of both worlds. But to be honest, I don't see a real use case for implementing this interface, and it can always be added later as an explicit interface implementation without breaking existing users.

We could use a copy constructor like var clone = new Crc32(existingInstance); or a public static Crc32 Clone(Crc32 instance) method. However, I prefer the Clone() method, which is an established pattern to copy instances.

Risks

I don't see any risks of breaking changes, performance regressions etc. (apart from the slight increase in code size).

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-approvedAPI was approved in API review, it can be implementedarea-System.IO.Hashingin-prThere is an active PR which will close this issue when it is merged

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions