Unnecessary casting in IComparer?

I understand how to use the IComparer interface with helper classes that provide custom sorting methods. For example, here is a typical example that is very similar to all the examples I've seen on the Internet, including the Microsoft help page:

// This helper class is used to sort an array of people by name, // where 'Person' is a class type. public class PeopleNameComparer : IComparer { // Test the name of each object. int IComparer.Compare(object o1, object o2) { Person p1 = o1 as Person; Person p2 = o2 as Person; if (p1 != null && p2 != null) return string.Compare(p1.Name, p2.Name); else throw new ArgumentException("Parameter is not a Person!"); } } 

I also understand that if we have an array of type Person (myPeople), we can sort this array with:

 Array.Sort(myPeople, new PeopleNameComparer()); 

In this case, we create a new PeopleNameComparer object that is of type IComparer and passes it to the Array.Sort () method as the second parameter.

Now, to make things tidy, we can implement a property to provide the user of the object with a more convenient way to invoke custom sorting:

 public static IComparer SortByName { get { return (IComparer)new PeopleNameComparer(); } } 

What I donโ€™t understand with this property is why all the examples use (IComparer) cast to include the newly created helper class (PeopleNameComparer in this example) in the IComparer object when this object already has an IComparer type? I tried without casting and the code works fine:

 // This property seems to work fine without the cast? public static IComparer SortByName { get { return new PeopleNameComparer(); } } 

I could understand this if the 'new' keyword returned the normal System.Object vanilla type, which then had to be sent to the appropriate IComparer, but just can't see the need for a cast here. But I followed the example of Microsoft, and my example is similar to the example in my Pro C # book.

Is there any reason why a shot is needed here?

+4
source share
4 answers

Using explicit casts is more explicit. Forgive the truism .. but it is so. This helps make the code more readable.

In some cases, explicit casts can help runtime disambigateate cast if there are several possible parameters, but this does not look like a return type. Only in expressions. The following is a general example where you need an explicit expression in an expression:

 public class StringEnumerable : IEnumerable, IEnumerable<String> { IEnumerator<String> IEnumerable<String>.GetEnumerator() { yield return "TEST"; } public IEnumerator GetEnumerator() { // without the explicit cast of `this` to the generic interface the // method would call itself infinitely until a StackOverflowException occurs return ((IEnumerable<String>)this).GetEnumerator(); } } 

If you remove the explicit cast from a non-generic interface implementation, this will cause an infinite loop.

+2
source

Listing is redundant.

Perhaps this was necessary before the code was reorganized from something else.

As a rule, you see a lot of fluff left in the code during the long life cycles of the system when the projects changed.

You can also see other redundant constructs when language functions change (i.e., automatic C # properties) over time.

I think that redundant code reduces readability, and tools like Resharper will warn you and help you remove them.

+2
source

If your question is simply why the examples pass PeopleNameComparer to IComparer, you are right that this is not necessary. I would suggest that for clarity, you can demonstrate to beginners that the relationship between the result and the interface is implied.

+1
source

I donโ€™t know about โ€œallโ€ examples, but really two versions of the code should work the same way. Perhaps they just think that explicit casting is more readable.

+1
source

Source: https://habr.com/ru/post/1379325/


All Articles