.net 如何确定ToString方法是否返回对象类型名称和实际值?

.net 如何确定ToString方法是否返回对象类型名称和实际值?,.net,caching,tostring,.net,Caching,Tostring,我打算使用ToString()方法创建缓存键。该缓存将用于缓存方法级调用,并且将使用参数名称和相应的值来构造密钥。因为这个缓存是为一个大型库构建的,所以我无法确保每个方法都只有值类型参数,或者所有类都实现序列化。我需要在运行时确定对ToString的调用返回的是一个实际值,而不是类型名,这样就可以禁止该方法调用参与缓存 例如,考虑下面的方法及其调用< /P> AccountDetails GetDetails(int groupId, Account account) { var ac1

我打算使用ToString()方法创建缓存键。该缓存将用于缓存方法级调用,并且将使用参数名称和相应的值来构造密钥。因为这个缓存是为一个大型库构建的,所以我无法确保每个方法都只有值类型参数,或者所有类都实现序列化。我需要在运行时确定对ToString的调用返回的是一个实际值,而不是类型名,这样就可以禁止该方法调用参与缓存

例如,考虑下面的方法及其调用< /P>

AccountDetails GetDetails(int groupId, Account account)
{
    var ac1 = new Account( accountId = 123 };
    var ac2 = new Account( accountId = 555 };
    var return1 = GetDetails(15, ac1);
    var return2 = GetDetails(15, ac2);
}

在本例中,我将缓存键构造为“groupId=15+account=namespace.account”,从而导致不正确的冲突。如何在运行时检测对account.GetString()的调用将返回类型名?

我不知道“ToString”方法中的实现是什么(您知道,有人在“Object”中重载了“ToString”,但实现方式与在“Object”中实现的方式相同)

不能将ToString用作对象的散列。考虑两个逻辑上不同的对象,如两个全名相同、ID不同的“学生”对象(或一些非ascii值,如图片)。您需要使用真正的哈希-请参阅“GetHashCode”


如果“GetHashCode”不是一个选项,我们将需要更多信息(如“为什么”)

您不应该将字符串用于常规缓存键。这并不是ToString的设计初衷。相反,应该使用
Equals
GetHashCode
检查相等性。当然,像
ToString
,每个对象都有
等于
GetHashCode
方法。。。但幸运的是,有一个接口提供了一个更强烈的信号,表明一个类型确实是为平等而设计的

因此,对于任何给定类型
X
,只需检查该类型是否实现了
IEquatable
。如果是这样,那么将其用作缓存密钥应该是合理的。如果要编写泛型方法,可以强制执行以下操作:

void Foo<T>(T key, /* other parameters */) where T : IEquatable<T>
void Foo(T键,/*其他参数*/),其中T:i可满足

为什么要使用
ToString
进行缓存?那不是它的目的。为什么不使用
GetHashCode
Equals
,它们通常更适合缓存-或者创建自己的接口来实现…是的,想要解决停止问题来确定任意方法调用将返回什么,这似乎是绝对疯狂的,当
GetHashCode
已经被构建和定义以提供实例之间的良好区分时。同意,ToString()就是为了提供一个来自对象的人类可读字符串。如果您确实想使用您提到的字符串作为缓存键,那么我将添加一些接口
ICacheable
,该接口提供
string GetCacheKey()
。但是使用字符串作为密钥不是效率低下吗?根据缓存方式的不同,
GetHashCode
最终将在字符串上被调用。@JonSkeet-我觉得这种情况类似于Http请求的输出缓存。确切的对象并不重要,但对象的价值很重要。我正在开发企业软件,拥有大量的代码库。我们知道我们不能缓存每个边界调用的输出,但是对于只接受值参数的方法,可以通过从参数名称和值构建缓存键。这就是为什么ToString()和opt-out引用类型没有提供合适的值。@zync:听起来
GetHashCode
Equals
正是您应该使用的,而不是字符串表示形式。例如,您只能接受实现
IEquatable
的类型。这将提供比使用ToString更好的体验,IMO。没有答案(更多的是注释,与现有注释相同)请注意,
GetHashCode
不应单独使用。与加密哈希不同,来自对象的哈希代码在易于创建的情况下完全可以合理地发生冲突
GetHashCode
应作为检查相等性的第一步,而不是最后一步。因此,理论上这是可行的,但对于我的特定场景,我需要从传入的“对象”中获取哈希代码。问题是,确定传入对象是否实现IEquatable的唯一方法似乎是执行target.GetType().GetInterface(typeof(IEquatable.FullName))。这会导致反射并降低性能。@zync:不幸的是,您没有给我们足够的上下文来帮助您-我们不知道您是否有泛型方法等。您可以轻松地按类型保留缓存,尽管您根本不需要使用名称-使用
typeof(IEquatable)。MakeGenericType(target.GetType())
,然后检查该类型是否实现了该特定接口。很抱歉(这里是凌晨3点)。没有-我没有泛型函数。我使用unity截取截取函数。我收到的是有关截获的方法和参数“object”集合的信息。我需要弄清楚这些对象是否可以作为GetHashCode+Equals的候选对象。我试试你说的;另一个选项似乎是target.GetType().GetInterfaces(),然后将字符串与typeof(IEquatable.FullName)进行比较。但是您的建议似乎比类型名上的字符串比较更可靠。@zync:它也应该更快:)您可以使用
type.IsAssignableTo
作为检查接口实现的一种方法(还有各种其他方法)。但是从类型缓存到“这是否有效”可能很值得一做。是的。这很有效。我们将检查性能。幸运的是,这将在服务器端运行:)