C# 在C中散列委托函数#
如何在C#中获取委托函数的哈希值。我想知道是否有不同的代表被派到我的职能部门。我的代码如下所示:C# 在C中散列委托函数#,c#,hash,delegates,C#,Hash,Delegates,如何在C#中获取委托函数的哈希值。我想知道是否有不同的代表被派到我的职能部门。我的代码如下所示: public string GetContent(Func<string, bool> isValid) { // Do some work SomeFunctionToHashAFunction(isValid) } GetContent(new Validator("foo"), new ValidatorEqualityComparer()); 公共字符串GetContent(
public string GetContent(Func<string, bool> isValid)
{
// Do some work
SomeFunctionToHashAFunction(isValid)
}
GetContent(new Validator("foo"), new ValidatorEqualityComparer());
公共字符串GetContent(Func是有效的)
{
//做些工作
SomeFunctionToHashAFunction(有效)
}
我会使用.GetHashCode(),但是.NET框架不能保证这些是唯一的
编辑
我有一些正在验证的缓存内容,但我只想验证一次。但是,如果验证函数更改,则需要重新验证缓存的内容。我不确定ObjectedGenerator是否能在这个实例中工作,因为我需要确定两个匿名函数是否具有相同的实现。根据定义,哈希不能保证是唯一的,因此哈希不是您想要的 相反,您要确定委托的实例以前是否已“看到”。为此,您可以使用:
您甚至可以进一步简化并在设置
IsValidHandler
属性时执行验证(不在GetContent
方法中)。GetHashCode在不同对象之间是唯一的,系数为2^122,这看起来相当安全
否则,创建一个类,添加一个func属性和一个bool,即HasBeenSeen
应该完成工作。散列不是唯一的。就相等而言,唯一可以使用它们的是确定两个对象是否不相同。因此,它们可以用作快速第一次测试;如果散列值不同,则没有必要进行进一步的比较;这两个对象不一样。如果散列确实匹配,则对象可能相同,但也可能不同,因此您需要执行更深入的分析以确定相等性。为什么不使用存储委托?然后,您只需使用
.Contains(isValid)
检查委托是否已被授予
换句话说,有人已经解决了这个问题。您没有理由也解决它。没有(至少是非完全黑客式的)散列匿名函数/委托的方法。即使函数实现是相同的,它也可能是一个闭包——因此验证结果可能会根据上下文状态而有所不同。考虑这个例子:
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
因此,确保验证函数是否唯一的唯一方法是让调用方定义验证实现的唯一性,并让调用方将该信息传递给您。您必须切换到使用某种验证器接口,大致如下:
//
// 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;
}
}
因此这里要注意的最重要的部分是,在实现
ValidatorEqualityComparer.GetHashCode()
时,使用验证器对象状态(基于对象值)散列。只有这样才能确保验证逻辑的真正唯一性。根据定义,哈希永远不能保证唯一。事实上,保证是两个在等于中返回true的对象返回相同的哈希代码(而不是相反)。这就是为什么GetHashCode应仅用于查找,然后应使用Equals进行最终比较,以验证两个对象是否真正匹配。一些有趣的阅读资料:。引用:“不管怎样,在大约9300次尝试后,你最终有1%的几率发生碰撞,而在仅77000次尝试后,有50%的几率发生碰撞。”哈哈,很好。我以前从未见过,但这本书读得真不错。我推动将guid重命名为GNUIDs。不是很吸引人。-1“相当安全”-如果你认真对待软件工程,你就不能接受“相当安全”作为原则。对于冲突,我不同意,如果相当安全的解决方案是30分钟,99%安全的解决方案是3天,我就采用30分钟的经济解决方案,周期。如果这是安全原则,我完全同意,但是如果你对工程软件很认真,你就应该认真对待,不要浪费你的雇主的时间和金钱去做一件不是绝对重要的事情。OP想要检查他以前是否看到或没有看到一个代理,他显然不能接受GetHashCode
不是唯一的。因此,你的“相当安全”的推理是错误的。顺便说一句,我是雇主,所以我可以自由决定什么是浪费,什么不是;-)+一个很好的解决方案,肯特!我以前甚至不知道ObjectiveGenerator-这也将解决我的一些问题!我希望我能给你+2:)
//
// 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;
}
}
GetContent(new Validator("foo"), new ValidatorEqualityComparer());