I understand how to use the IComparer interface with helper classes which provide custom ways to sort. For example, here is a typical example which is very much like all the examples I have seen on the web including Microsoft's online 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 then sort this array with:
Array.Sort(myPeople, new PeopleNameComparer());
In this case we are creating a new PeopleNameComparer object which is of type IComparer and passing it into the Array.Sort() method as a second parameter.
Now to make things neater, we can implement a property to provide the object user with a more friendly way to invoke the custom sort:
public static IComparer SortByName
{ get { return (IComparer)new PeopleNameComparer(); } }
What I don't understand with this kind of Property is why do all the examples use the (IComparer) cast to cast the newly created helper class(PeopleNameComparer in this example) into an IComparer object when this object is already of type IComparer? I have tried without the cast and the code appears to work fine:
// This property seems to work fine without the cast?
public static IComparer SortByName
{ get { return new PeopleNameComparer(); } }
I could understand it if the 'new' keyword returned a plain vanilla System.Object type which would then have to be casted to the appropriate IComparer, but just cannot see the need for the cast here.
But I followed Microsoft's example, and my example is similar to an example in my Pro C# book.
Is there any reason why a cast would be necessary here?
Using an explicit cast is more explicit. Pardon the truism.. but it's just that. It helps make the code more readable.
In some cases explicit casts can help the runtime disambiguate a cast if there are multiple possible options but that doesn't seem to occur with return type. Only in expressions. Following is a common example where you would need an explicit cast 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 non-generic interface implementation it will cause an infinite loop.
The cast is redundant.
Perhaps it may have been necessary before the code was refactored from something else.
Typically you see a lot of fluff left in code over long system life-cycles where designs have changed.
You may also see other redundant constructs when language features have changed (i.e. C# automatic properties) over time.
I think redundant code decreases readability and tools like Resharper will warn you and help you remove them.
If your question is simply why the examples cast the PeopleNameComparer to IComparer, you are correct that it is not necessary at all. I would imagine it is for clarity to demonstrate to beginners that there is the implied relationship between the result and the interface.
I don't know about "all" examples but indeed the 2 variants of code should work identically. Maybe they just think that explicit casting is more readable.
Related
When I was learning C# generics, some articles mentioned using generics is type-safe during execution by preventing the usage of data whose type is different from the one used in the declaration.
Link
I dont get why this should be an issue, if type is wrong shouldn't it crashed when build?
I'm curious about when and how this kind of problem could happen.
I'm curious about when and how this kind of problem could happen.
Basically, when using types that don't support generics but could. The classic example is probably ArrayList - the pre-generics equivalent of List<T>. ArrayList.Add just accepts object, so you can add anything into it - but typically code assumes just a specific type. So for example:
var people = new ArrayList();
people.Add(new Person("Jon"));
// ... later in the code
foreach (string name in people)
{
Console.WriteLine(name);
}
That crashes with a ClassCastException, because the list contains a Person reference, which is then implicitly cast to a string reference. That wouldn't happen with generics, where you'd have either a List<Person> or a List<string>, and spot errors at compile-time.
Generics are indeed type safe in compile time. I'd say that article in the sentence:
Client code that uses generics is type-safe during execution by
preventing the usage of data whose type is different from the one used
in the declaration
is referring to the implicit benefit of eliminating runtime invalid cast exceptions.
Generics provide type safety during compile-time, meaning you can't compile your code if the generic constraint is violated. And that is almost always preferable over a runtime exception.
void DoSomething<T>(T foo) where T : FooBase { }
If I try now to write code like this:
var myBar = new Bar(); // Does not inherit from FooBase
DoSomething(myBar);
Then I get this:
error CS0311: The type 'Bar' cannot be used as type parameter 'T' in the generic type or method 'DoSomething(T)'. There is no implicit reference conversion from 'Bar' to 'FooBase'.
And this happens during compile time. Perfect.
You might have also seen generics without any constraint:
void DomSomething<T>(T foo);
This will go a bit away from your original question, but one could ask what is the benefit over let's say: DoSomething(object obj). And here we have a difference between value types and reference types - namely boxing and unboxing happens when using the version with object.
So generics can also have some performance benefits, next to the type safety and reusability aspect.
One of the major benefits of generics in not just type-safety as is, but allowing writing generalized code while still maintaining type-safety and without degrading performance for value-types. For example we can generalize over collection of interface:
public interface IHaveId { int Id {get;}}
public T GetOrAddById<T>(IList<T> col, int id, T val) where T : class, IHaveId
{
var item = col.FirstOrDefault(x => x.Id == id);
if (item == null)
{
item = val;
col.Add(item);
}
return item;
}
Now you can't pass anything that does not implement the concrete interface.
Before the generics the only way of having generalized collection would be something like ArrayList (which can be compared to List<object>), so user could put anything in it without any type-safety.
I have a static function:
public static MyCollection<T> Parse<T>(string? json) where T : BaseClass
{
...
}
And it works fine. It makes decisions internally based on the type and produces the correct collection.
But, the collection I want is based on a file name coming in from another source and I was hoping to have one collection and dynamically set the type, as in:
Type t;
if (name == "Certain name") t = typeof(CertainChildClassOfBaseClass);
if (name == "Other name") t = typeof(OtherChildClassOfBaseClass);
var myCollection = ParsingService.Parse<t>(jsonString);
This obviously doesn't work, but is what I'm trying possible? I don't really want to write a bunch of if/else blocks with nearly identical content just so each one can have a different type (I already wrote those type-specific blocks inside the Parse function - doing the same branching twice seems like maybe I've made a more fundamental mistake). I am open to suggestions on how to do this the "right" way. Maybe I have to do this with reflection, which doesn't thrill me, but isn't the end of the world. One possible issue is the my parsing service is static.
Help is always appreciated.
Usually, I would recommend making Parse non generic, and then have a generic overload:
public static MyCollection<BaseClass> Parse(Type type, string? json)
{
...
}
public static MyCollection<T> Parse<T>(string? json) where T : BaseClass
{
return (MyCollection<T>)Parse(typeof(T), json);
}
But you can't make MyCollection contravariant because it's a concrete class, so that cast is illegal. And anyway, contravariant containers are dangerous to use (just look at arrays, for example).
The other method is to use reflection to get the version of the method you want (a process known as "closing" the generic type):
var genericMethod = typeof(/* class containing Parse */).GetMethod("Parse");
var method = genericMethod.MakeGenericMethod(type); // type will be substituted for your 'T', above
object collection = method.Invoke(json); // call the method
And here we hit another snag: collection's type will be object, and you need to cast it to something else. But you can't use MyCollection<T> because you don't know T, and you can't use MyCollection<BaseClass> because, well, no contravariance, again.
So really the main blocker is that MyCollection type. As long as it is that way, you have no easy way to go around it. You could instead return a non generic collection, like ICollection or IList, but then you lose type safety and you'll have to keep casting more later. It's up to you, really.
I am trying to wrap my head around all the list Interfaces in C# (IEnumarable, IReadOnlyCollection) etc., and as part of that realized I do not really understand why the below code works. After all, the method has an IReadOnlyCollection as return type, but the varibale returned is of type Array (float[]). I realize that Array implements the IReadOnlyCollection interface, but I do not get how it converts from one to the other. Is it done in the background somehow?
private readonly float[] _location;
public Player()
{
_location = new float[3];
}
public IReadOnlyCollection<float> Location
{
get
{
_location[0] = Worker.Elements["lbXCoordinate"].Value;
_location[1] = Worker.Elements["lbYCoordinate"].Value;
_location[2] = Worker.Elements["lbZCoordinate"].Value;
return _location;
}
}
An object can be implicitly casted to any one of the interfaces that is implemented by its class; however, no conversion takes place - as Jon Skeet pointed out in a comment, it is the original array that is returned. To the caller, it will be "disguised" as an IReadOnlyCollection<float>, and the caller will ideally only perform operations from IReadOnlyCollection<float> on it. However, if the caller knows or suspects the actual type, the caller may decide to cast it back into a float[], and the encapsulation of your object will be breached. (This is risky for the caller, though, since if you change the actual type to List<float> at some point, the code that casts to float[] will break.) In order to ensure encapsulation, the object that is returned must itself protect its contents, so you should indeed create a class/struct with private (or no) setters. Then, your code will become more readable and self-documenting as well.
The above code works, because IReadOnlyCollection interface implements IEnumerable and Array abstract class also implements IEnumerable interface. So when you, return array of float for a method of IReadOnlyCollection return type, an upcasting is done internally to IEnumerable.
I hope this is what you are looking for.
No, Array does not implement IReadOnlyCollection, please refer below link:
http://msdn.microsoft.com/en-IN/library/system.array(v=vs.110).aspx
And IReadOnlyCollection also implements same Interface IEnumerable, please refer below link:
http://msdn.microsoft.com/en-us/library/hh881542(v=vs.110).aspx
Now, when you are trying to return an array for a method of type, IReadOnlyCollection, it is a type safe conversion to their base type which is IEnumerable.
My application uses
var results= websiteDetail.Detail.GetProductDetails<MyProduct>(code, websiteDetail.Detail.NegativeWords);
which in turn now calls
public List<T> GetProductDetails<T>(string websiteHtmlCode, List<string> negativeWords)
{
List<T> result = new List<T>();
foreach (var item in GetProducts(negativeWords))
{
result.Add((T)Convert.ChangeType(item, typeof(T)));
}
return result;
}
private List<MyProduct> GetProducts(List<string> negativeWords)
{
// logic
}
However, if I update the code to:
public List<T> GetProductDetails<T>(string websiteHtmlCode, List<string> negativeWords)
{
return GetProducts(negativeWords); //ERROR
}
I get told off with:
Cannot implicitly convert type 'System.Collections.Generic.List<MyProduct>' to 'System.Collections.Generic.List<T>
I then updated the code, to remove the List to work with single objects, the same issue persists.
Why do I have to call the ListConvert.ChangeType when the T is already of that type?
The problem here lies in understanding how C# generics work.
In C++, there was a concept of template specialization. That is, you could write:
void Foo<T> {}
void Foo<int> {}
If T was an int, it would use the specialized version, otherwise the generic. This is NOT allowed in C# generics. Either everything is generic, or everything isn't. When you write
public List<T> GetProductDetails<T>(string websiteHtmlCode, List<string> negativeWords)
You are now in the land of generics (albeit a generic method instead of class). Because you are now in the land of generics, making a call to a specific function:
List<MyProduct> GetProducts
Doesn't make any sense. What if T was object, or String? Returning a list of MyProduct would be very confusing, and almost assuredly fail when trying to cast (as your "working" code does). In other words, if you are always returning a List<MyProduct>, why bother with the generic (hence my earlier comment, they need to all be generic, or all concrete, you can't mix!).
The general rule of generics is "T is an object". That is all it is, and all it ever can be. If you need more specialization than just object, you need to add a where clause to your generic type argument. I kind of doubt you actually need that in this case, since you it looks like you are just doing a web request. You should be able to just change your function to:
List<T> GetProducts
At this point you may want to consider making the class generic as well, but that is up to you. If you can't make that change, I would remove the genericness from your method. You could do a switch on the type oF T but that isn't any better, and is very hard to understand/read.
MSDN for generic type constraints (where): MSDN
Please let me know if I can clarify anything!
-Edit- Alternative question/example How do i cast A to object to class A when B can typcast to A?
I have class A, B, C. They all can implicitly convert to a string
public static implicit operator A(string sz_) { ... return sz; }
I have code that does this
object AClassWhichImplicitlyConvertsToString
{
...
((IKnownType)(String)AClassWhichImplicitlyConvertsToString).KnownFunc()
}
The problem is, AClassWhichImplicitlyConvertsToString isnt a string even though it can be typecast into one implicitly. I get a bad cast exception. How do i say its ok as long as the class has an operator to convert into a string?
There is almost certainly a better way of doing whatever it is you're trying to do. If you provide more context, you'll get more helpful answers.
If instead of (or as well as) making your classes implicitly covert to string you also give them a ToString override, you can then say:
((KnownType)AClassBlah.ToString()).KnownFunc()
However, you'll then get an exception on trying to cast a string into KnownType. So I have to ask: why are you trying to go via string in this situation? Casts are generally an ugly-ass thing that make you think "Maybe my design needs refactoring one day". They're not something you design into your class library as a recommended usage pattern. They're a low-level facility with predictable behaviour, so there is no way (and no good reason to provide a way) to override what an explicit cast does.
Update
Judging from your comment you are mixing together runtime polymorphism and static (compile time) conversion. They don't mix too well. Are you previously a user of dynamically typed languages? It seems like you might be. If you have a method:
void FiddleWithObject(object obj)
{
// whatever
}
Then the author of that method has no compile-time knowledge of what operations are available on obj. So they can say:
void FiddleWithObject(object obj)
{
if (obj is IFiddly)
{
// Cool
obj.Fiddle();
}
else
throw new Exception("Wrong type of object");
}
This then blows up at compile time for classes that aren't IFiddly. But in a statically typed language, you can say:
void FiddleWithObject(IFiddly obj)
{
obj.Fiddle();
}
This will blow up at compile time if the wrong kind of object is passed, and you don't need to check anything at runtime. Less code, bugs found sooner... how neat is that?
The implicit conversion feature is part of the operator overloading set of features. These are all very much tied to static types. They are resolved at compile time based on the known type of the object. So if you don't know the actual class of an object, there is no (built-in) way to call operators on it. It just doesn't mix with dynamic typing.
If it is possible to get a string (such as a "name") from an IFiddly object, then you can make it a property on that interface:
public interface IFiddly
{
void Fiddle();
string Name { get; }
}
Or (as I noted before) you could just override ToString on any object, as that's a virtual method on the object class that all classes ultimately inherit from. So by saying:
var str = someObject.ToString();
You are going to be calling the ToString implementation defined in whatever class someObject is an instance of.
In summary:
virtual and abstract methods, and supported interfaces: these are for dynamic, runtime typing and polymorphism.
operator and implicit conversion overloading (and generics): these are for compile-time, static typing.
casts are disgusting.