我想为另一种类型创建一个包装类。这种方法很好,直到需要(引用)-equal对象需要(引用)-equal包装器。
一个例子:
public interface ITest<T>
{
T GetInstance(bool createNew);
}
public class Test : ITest<Test>
{
private static Test instance;
public Test GetInstance(bool createNew)
{
if (instance == null || createNew)
{
instance = new Test();
}
return instance;
}
}
public class TestWrapper : ITest<TestWrapper>
{
private readonly Test wrapped;
public TestWrapper(Test wrapped)
{
this.wrapped = wrapped;
}
public TestWrapper GetInstance(bool createNew)
{
return new TestWrapper(wrapped.GetInstance(createNew));
}
}
只要参数Test.GetInstance
为createNew
, false
将始终返回相同的实例。
相比之下TestWrapper.GetInstance
总是返回一个新实例。
由于我希望能够用Test
替换TestWrapper
,因此我搜索一个解决方案,以便最后,如果Test返回一个新实例,则包装器仅返回一个新实例。但是,TestWrapper应该不了解Test的内部。
测试代码是
private static void RunTest<T>(ITest<T> cls)
{
var i1 = (ITest<T>)cls.GetInstance(false);
var i2 = (ITest<T>)cls.GetInstance(false);
var i3 = (ITest<T>)cls.GetInstance(true);
var dic = new Dictionary<ITest<T>, bool>();
if (!dic.ContainsKey(i1)) dic.Add(i1, false); else dic[i1] = true;
if (!dic.ContainsKey(i2)) dic.Add(i2, false); else dic[i2] = true;
if (!dic.ContainsKey(i3)) dic.Add(i3, false); else dic[i3] = true;
Console.WriteLine(string.Join(", ", dic.Select(a => a.Value.ToString())));
}
期望的结果是
True, False
如果将new Test()
传递给该方法,那就是你得到的。
如果您通过new TestWrapper(new Test())
,则会获得
False, False, False
有一个基于简单缓存(Dictionary<Test, TestWrapper>
)的解决方案 - 但有了这个,我会在内存中保留许多实例而不再使用它们(并且GC无法收集这些实例,因为有一个参考他们)。
我稍微使用了WeakReferences
,但我找不到可以用来存储WeakReference
的密钥 - 因此我必须遍历缓存列表并搜索正确的实例很慢。此外,我要为每个成员(使用它自己的缓存)实现这个解决方案,这似乎不是一个很好的解决方案......
我希望我已经充分解释了我的问题;)所以,我的问题是:
object.ReferenceEquals
WeakReference
)我无法访问Test
类,只能访问使用它的代码(只要它实现了接口,我就可以传递任意实例)
答案 0 :(得分:1)
不,你不能作弊object.ReferenceEquals()
。但是,object.ReferenceEquals()
是故意使用的很少,通常情况下,事情确实需要引用相等。
运行时需要它才能使事情正确。例如。如果实例用作
中的键Dictionary<>
实际上,运行时通常使用单个对象的.GetHashCode()
和.Equals()
行为,但恰好如果您没有在类中覆盖该行为,则基数{{1默认情况下,这些方法的实现依赖于对象引用。
因此,如果您能够更改System.Object
类和Test
类的代码,则可以在这些类中覆盖这些相等方法,以确保它们将等效对象识别为相等。
另一种(通常更好的)方法是创建一个TestWrapper
实现,以便在您的特定用例中使用。您在IEqualityComparer<>
中提到了密钥:您可以在创建字典时为字典提供Dictionary<>
实例,以便以完全符合您需要的方式测试它。
IEqualityComparer<>