Hash delegate function in C #

How can I get the hash of a delegate function in C #. I want to know if different delegates are being sent to my function. My code looks something like this:

public string GetContent(Func<string, bool> isValid) { // Do some work SomeFunctionToHashAFunction(isValid) } 

I would use .GetHashCode (), but the .NET framework does not guarantee that they will be unique.

EDIT I have cached content that I check, but I just want to check it. However, if the verification function is changed, then I will need to re-check the cached content. I'm not sure if the ObjectIdGenerator will work on this instance, since I need to determine if two anonymous functions have the same implementation.

+4
source share
5 answers

There is no (at least not completely hacked) way to hash an anonymous function / delegate. Even if the implementation of the function is the same, it can be a closure, so the result of the check may differ depending on the context state. Consider this example:

 public class Validator { public string SomeState { get; set; } public Validator(string someState) { SomeState = someState; } public bool IsValid(string input) { return input == SomeState; } } // assume your 'input' being validated is "foo" GetContent((new Validator("foo")).IsValid); // IsValid returns true GetContent((new Validator("bar")).IsValid); // IsValid returns false 

Thus, the only way to verify that the validation function is unique would be for the caller to determine the uniqueness of the validation implementation and provide the caller with this information for you. You will need to switch to using some kind of validator interface, something like this:

 // // Your code // public string GetContent(IValidator validator, IEqualityComparer<IValidator> comparer) { // for tracking used validators, use instance // of 'new HashSet<IValidator>(comparer)' // this will give you a hashset of unique validators } public interface IValidator { bool IsValid(string input); } // // Your callers code // public class Validator : IValidator { // same as Validator class code above } public class ValidatorEqualityComparer : IEqualityComparer<Validator> { public bool Equals(Validator v1, Validator v2) { return GetHashCode(v1) == GetHashCode(v2); } public int GetHashCode(Validator v) { int hCode = GetMyStringHash(v.GetType().GUID.ToString() + v.SomeState); // as for GetMyStringHash() implementation for this example, // you can use some simple string hashing: // http://www.techlicity.com/blog/dotnet-hash-algorithms.html return hCode; } } 

Then you can call your method as follows:

 GetContent(new Validator("foo"), new ValidatorEqualityComparer()); 

So, the most important part that should be noted here is that when implementing ValidatorEqualityComparer.GetHashCode() you use a validator object hash (based on the value of the object) . Only this guarantees the true uniqueness of the verification logic.

+2
source

By definition, a hash is not guaranteed to be unique, so hashing is not what you want.

Instead, you want to determine if a delegate instance was previously considered. For this you can use ObjectIdGenerator :

 private static readonly ObjectIdGenerator oidg = new ObjectIdGenerator(); public string GetContent(Func<string, bool> isValid) { bool firstTime; oidg.GetId(isValid, out firstTime); if (!firstTime) { ... } } 

However, even with this technique, there are some pitfalls to be aware of:

  • ObjectIdGenerator stores a reference to every object that you pass to it
  • Delegates with the same function are separate entities and therefore return different identifiers

Perhaps if you explain exactly what you are trying to achieve, there may be a much better way to do this.

EDIT . Given your updated requirements, I will simply define the validation delegate as a property. If the property changes, you know that you need to repeat the check. GetContent() will therefore not require any parameters:

 public Func<string, bool> IsValidHandler { get { return this.isValidHandler; } set { this.isValidHandler = value; this.requiresValidation = true; } } public string GetContent() { if (this.requiresValidation && this.isValidHandler != null) { // do validation this.requiresValidation = false; } // return content } 

You can even simplify and check if the IsValidHandler property IsValidHandler set (not in the GetContent method).

+4
source

Hashes must not be unique. As for equality, the only thing you can use to do this is to determine if two objects are the same. Thus, they can be used as a quick first test; if the hashes are different, there is no use for further comparisons; two objects do not match. If the hashes match, the objects may be the same, but they may also not be, so you need to do a deeper analysis to determine the equality.

+2
source

Why not just use a HashSet to store delegates? Then you can simply use .Contains(isValid) to check if the delegate is already provided.

In other words, someone has already solved this problem. There is no reason to solve it.
0
source

GetHashCode will be unique for different objects with a coefficient of 2 ^ 122, which seems pretty safe.

Otherwise, create a class, add the func and bool property, which is HasBeenSeen.

Must complete the task.

-1
source

Source: https://habr.com/ru/post/1344320/


All Articles