Comments (8)
This is complex issue, related to missing GetHashCode
implementation for object. Without implementation β object reference is used. So, after cloning clonedObject
has another reference and GetHashCode
for it returns another value.
In real situation correct implementation of GetHashCode is very recommended. I'll think about possible variants of mitigation of this problem.
from deepcloner.
Ran into this issue after switching to DeepCloner from BinaryFormatter. BinaryFormatter had the same fundamental issue, but I was able to work around it by using the [OnDeserialized] hook like this:
public class MyObject<T> : IList<T>
{
private HashSet<T> _uniqueItemTracker = new HashSet<T>();
//Omitting IList<T> implementation
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
//After cloning, OnDeserialized invoked and the _uniqueItemTracker is re-populated by creating a new HashSet off the current contents
_uniqueItemTracker = new HashSet<T>(this);
}
}
This doesn't solve the fundamental problem, but a post-DeepClone hook would at least allow us to write code to fix it ourselves.
from deepcloner.
Currently, I'm trying to find best solution to mitigate this issue.
E.g. this code will not work by design (we clone set entirely but check with non-cloned object).
var key = new object();
var set = new HashSet<object> {key};
var cloned = set.DeepClone();
Assert.That(cloned.Contains(key)); // failed
This case can occur in any complex cloning and cannot be solved without custom handlers.
For you case, you can wrap set with new set, but EqualityComparer can be passed to HashSet (so, we need to pass it to new Set). Also, there are a lot of Dictionaries and Sets implementations with custom behavior, so, it hard to make correct general cloning.
from deepcloner.
Is there any update on this? There's some weird things going on with strings as well.
Note that this only fails on .net 6.0 and passes on netcoreapp3.1. It could probably have something to do with an optimization in HashSet for when T == typeof(string).
var set = new HashSet<string> { "value" };
set.Contains("value").Should().BeTrue(); // pass
var cloned = set.DeepClone();
cloned.Contains("value").Should().BeTrue(); // pass
var copyOfSet = new HashSet<string>(set, set.Comparer);
copyOfSet.Contains("value").Should().BeTrue(); // pass
var copyOfCloned = new HashSet<string>(cloned, cloned.Comparer);
(copyOfCloned.ToArray()[0] == "value").Should().BeTrue(); // pass
copyOfCloned.Contains("value").Should().BeTrue(); // fail
from deepcloner.
If I hack together a separate processing method for HashSet, where I just return new HashSet<string>(objFrom, objFrom.Comparer)
, this test works. so it's probably only related to strings...
from deepcloner.
It's really strange, but interesting issue.
When HashSet created it checks:
- is comparers are same (for strings it should be true, but there are lot of internal magic to create Comparer.Default) - in this case it just copies internal HashSet objects
- if it differs code like to
new HashSet(comparer).UnionWith(source.AsEnumerable())
In both cases result should be identical. So, I'll try to reproduce problem and found a source of this issue.
from deepcloner.
I found an issue and fix it (will do some more tests and will publish new version in some days).
Problem only with strings (but another code can also cause similar problems).
HashSet in .NET6.0 uses special comparer for strings if no specific comparer is provided. Also, it returns non-real Comparer when you ask for it (it uses NonRandomizedStringEqualityComparer but returns GenericEqualityComparer).
When you create new instance of HashSet, it checks comparer == EqualityComparer<string>.Default
- and it fails for cloned comparer. So, HashSet began to use GenericEqualityComparer instead of default and it produces different hash code
So, it real .NET magic and it needs to be analyzed.
from deepcloner.
Yeah I saw that too, not sure what's exactly going on there. Looking forward to a new release. I've tested a workaround where in the deep cloner code I detect instances of HashSet and simply use a new HashSet<string>(source, source.Comparer)
to create the clone, this seems to work pretty good.
from deepcloner.
Related Issues (20)
- This exception is occasionally thrown in clones βmust be writeable (Parameter 'left')β HOT 4
- Request for info (country of origin) HOT 4
- Support for cloning child to parent type HOT 2
- the program crashed when i deepclone opencvsahrp Mat HOT 3
- How to only clone the common properties? HOT 4
- Latest change has not been published to NuGet HOT 1
- Why version 0.X? HOT 3
- Exception: An instance of the __ComObject type cannot be created unless the type has been obtained using GetTypeFromProgID or GetTypeFromCLSID. HOT 4
- program crashed when deepclone multidimensional zero-length array HOT 1
- Dependency on BinaryFormatter? HOT 1
- Possible Heap Corruption and Garbage Collection Interference... HOT 4
- When Object have navigation property, DeepClone throw exception. HOT 5
- Better error reporting HOT 1
- No stable cloning of `System.Drawing.Font` object HOT 6
- Memory corruption and program crash when cloning TaskCancelledException
- NHibernate Invalid cast exception
- Can't clone dictionary HOT 4
- Clone Action<T> delegate is incorrect
- Netstandard upgrade HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from deepcloner.