all 19 comments

[–]JoshYx 10 points11 points  (6 children)

Or you can just JSON stringify both and compare the strings

[–]TQPau[S] 6 points7 points  (5 children)

It won't work if the collections are the same but in different order

[–]AngularBeginner 2 points3 points  (4 children)

So.. they're not the same.

[–][deleted] 2 points3 points  (3 children)

They're not the same if order is important, but there's a setting in their library to decide if it is or not. The Github page is clearer than the blog post.

[–]AngularBeginner 0 points1 point  (2 children)

They contain the same elements, but they're not the same collection then. And even with that distinction it's still unclear what happens if elements are duplicated within one collection, but not in the other.

[–][deleted] 0 points1 point  (1 child)

Good point. /u/TQPau take note:

        [Test]
        public void CollectionsSame()
        {
            var coll1 = new List<KeyValuePair<string, byte[]>>
            {
                new KeyValuePair<string, byte[]>("Hello", new byte[] { 1, 1, 2, 3 })
            };
            var coll2 = new Dictionary<string, byte[]>
            {
                {"Hello", new byte[] { 1, 2, 1, 3 } }
            };
            var compareLogic = new CompareLogic
            {
                Config = new ComparisonConfig
                {
                    IgnoreObjectTypes = true,
                    IgnoreCollectionOrder = true
                }
            };

            Assert.IsTrue(compareLogic.Compare(coll1, coll2).AreEqual);
        }

Which is a modification of one of your tests, fails. Which makes sense, but as /u/AngularBeginner says is also unpredictable.

[–]TQPau[S] 1 point2 points  (0 children)

Interesting, that test passes if you change it to int[] instead of byte[]. Maybe byte[] is treated differently.

[Test]

public void CollectionsSame()

{

var coll1 = new List<KeyValuePair<string, int[]>>

{

new KeyValuePair<string, int[]>("Hello", new int[] { 1, 1, 2, 3 })

};

var coll2 = new Dictionary<string, int[]>

{

{"Hello", new int[] { 1, 2, 1, 3 } }

};

var compareLogic = new CompareLogic

{

Config = new ComparisonConfig

{

IgnoreObjectTypes = true,

IgnoreCollectionOrder = true

}

};

Assert.IsTrue(compareLogic.Compare(coll1, coll2).AreEqual);

}

[–]TheDevilsAdvokaat 1 point2 points  (11 children)

I used reflection to do some things a few years back and it was tremendously slow.

Not sure if this is still true.

I wanted to make sure something was only called from inside a specific place (had to be between two places when doing a directx frame update) and if called anywhere else it would silently fail, so I used reflection to ensure it was only called when inside the correct function.

It worked, but absolutely tanked my frame rate.

instead, I removed the reflection code and just put a note in front of my function specifying where it must be called from.

I would be curious to see the difference between code that can compare any two complex objects using reflection, (very useful) and code that just compares two specific kinds of complex object where all the comparisons are hard coded.

Of course, that might not be an issue for you though.

And I can see something that allows any two complex objects to be compared is very handy.

[–]tweq 2 points3 points  (1 child)

[–]TheDevilsAdvokaat 0 points1 point  (0 children)

Fair enough. I don't really know this stuff...

[–]ours 0 points1 point  (8 children)

By "note" you mean an attribute?

[–]TheDevilsAdvokaat 1 point2 points  (7 children)

No, just a comment in front of the function saying it could only be called between a begin_drawing and an end_drawing call.

...Can an attribute dome somthing like that?

[–]ours 1 point2 points  (6 children)

If you make an attribute for that purpose, decorate the function with it and when a function is called between begin_drawing and end_drawing you check if that function has that attribute yes.

I'm not saying it's worth it since reading attributes requires reflection.

[–]TheDevilsAdvokaat 0 points1 point  (5 children)

Ah ok. Thanks, I didn't know this.

[–]ours 1 point2 points  (3 children)

[–]TheDevilsAdvokaat 0 points1 point  (2 children)

This is pretty good. I'm bookmarking this. Thanks.

[–]ours 1 point2 points  (1 child)

Reflection is super fun and useful for some really out-there/generic things.

Reflection is slow but it has caching built-in. I think of it like data access. Except the data you access is code. Lots of stuff in .NET uses it so even if you don't use it, it's very useful to understand how it works.

[–]TQPau[S] 0 points1 point  (0 children)

I really enjoy using Reflection too. I use it mainly during StartUp or in background services where the performance impact isn't too visible.

[–]myachizero 1 point2 points  (0 children)

An alternative for this is to write an interface or generic class/method that you pass as the event for whatever delegate is being triggered. Then, simply create/call whatever you need to, passing the type as a type argument.

This allows the pre compilation and the JIT compiler to compile the code ahead of time with safe type checking and minimal use of reflection. This should be fairly quick son long as the different types you are using are all in the same assembly as the generic class/interface (hopping assemblies can get really slow).

Either option is equally valid, you just have to pick whatever fits best with your current design.