【发布时间】:2012-09-29 16:52:36
【问题描述】:
我打算使用 ToString() 方法来创建缓存键。该缓存将用于缓存方法级别的调用,并且将使用参数名称和相应的值构造键。由于此缓存将为大型库构建,因此我无法确保每个方法都只有值类型参数或所有类都实现序列化。我需要在运行时确定对 ToString 的调用返回的是实际值而不是类型名称,以便可以禁止该方法调用参与缓存。
对于实例,请考虑以下方法及其调用
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进行缓存?那不是它的目的。为什么不使用GetHashCode和Equals,它们通常更适合缓存 - 或者创建自己的接口来实现...... -
是的,当
GetHashCode已经被构建和定义以提供实例之间的良好区分时,想要解决停止问题以确定任意方法调用将返回什么似乎是绝对疯狂的. -
同意,ToString() 就是为此目的,从对象中提供人类可读的字符串。如果您真的想使用您提到的字符串作为缓存键,那么我会添加一些接口
ICacheable,它提供string GetCacheKey()。但是使用字符串作为密钥不是效率低下吗?根据您的缓存方式,GetHashCode无论如何都会在您的字符串上被调用。 -
@JonSkeet - 在我看来,这种情况类似于 Http 请求的输出缓存。确切的对象并不重要,但对象的价值很重要。我正在开发具有大量代码库的企业软件。我们知道我们将无法缓存每个边界调用的输出,但是对于只接受值参数的方法,可以通过从参数名称和值构建缓存键来实现。这就是为什么不提供的 ToString() 和 opt out 引用类型是合适的值。
-
@zync:听起来
GetHashCode和Equals是正是你应该使用的,而不是字符串表示。例如,您只能接受实现IEquatable<T>的类型。这将提供比使用 ToString、IMO 更好的体验。