Interfaces no longer work when using custom collection class - c#

I have created a class, MonitoredCollection<T>, that basically encapsulates/mimics List but allows me to fire events on certain calls.
Now however, whereever there is a parameter that takes a MonitoredCollection, where T is an Interface, I can no longer pass a MonitoredCollection<T> where T is a class that implements that interface, like I could with a List.
I always thought that interfaces were a language 'feature' and therefore I don't need to implement anything more to support this, so what have I missed?
EDIT: Sorry, I made a mistake in that question, as João correctly pointed out List never worked in this instance so the question is as it stands without that!

Suppose you have a MonitoredCollection<SomeObject> instance, and you want to treat it as a MonitoredCollection<ISomeInterface> instance where SomeObject does in fact implement ISomeInterface. This does not create any problems for retrieving items from the collection, since object of type SomeObject can be converted to the interface type ISomeInterface.
However, for all the methods on your collection which modify the collection, such as those that assign a new value to an index, or insert a new item into the collection, this cast has created a whole suite of issues. I'd assume your MonitoredCollection<SomeObject> instance would have a method such as Add(SomeObject obj), which would insert a new object into the collection. After the cast, the signature on this method would be Add(ISomeInterface obj). This seems to make sense, but not all ISomeInterface objects are NECESSARILY SomeObject instances.
Because the casted object will allow operations on the collection that the original object wouldn't allow, the runtime won't allow this cast. C# 4.0 introduced covariance and contravariance to explicitly state what is valid for casts of this type, you can look into them for trying to solve this issue. However, you're really only going to have luck with a read only version of your collection (think List<T>.AsReadOnly()).

Unfortunately, you can't do that with a list either. The compiler still cannot convert the types. You need to use a generic method. See code below:
class Test
{
void DoTest()
{
MonitoredList<IInterface> mlist1 = new MonitoredList<Inherited>(); //Error
MonitoredList<Inherited> mlist2 = new MonitoredList<Inherited>();
DoSomething1(mlist2); //Error converting MonitoredList<Inherited> to MonitoredList<IInterface>
MonitoredList<IInterface> list1 = new MonitoredList<Inherited>(); //Error
MonitoredList<Inherited> list2 = new MonitoredList<Inherited>();
DoSomething2(list2); //Error converting List<Inherited> to List<IInterface>
DoSomething3<Inherited>(mlist2); //Works fine
DoSomething3(mlist2); //<Inherited> is redundant
}
void DoSomething1(List<IInterface> list)
{ }
void DoSomething2(MonitoredList<IInterface> list)
{ }
//Generic method
void DoSomething3<T>(MonitoredList<T> list) where T : IInterface
{ }
}
interface IInterface { }
class Inherited : IInterface { }
class MonitoredList<T> { }

Related

can C# generic parameters be cast?

I've written a method with the signature:
private List<ClientItem> ConvertToClientItems(BaseCollection<object> serverItems)
I'm trying to call it in the following manner:
ConvertToClientItems(approvedSellers);
where approvedSellers is of type BaseCollection<Seller> - with Seller being a class that I don't have control over.
Shouldn't this be possible? Visual Studio is throwing an error at me saying that it cannot cast BaseCollection<seller> to BaseCollection<object>.
Well, imagine code that looks like this:
private List<ClientItem> ConvertToClientItems(BaseCollection<object> serverItems) {
serverItems.Add(new Buyer());
}
This should compile, since a Buyer is an object.
However, if you pass a BaseCollection<Seller>, you just tried to add a buyer to a list of sellers.
Thus, the statement
BaseCollection<Seller> is a subtype of BaseCollection<object>
only holds if BaseCollection ensures that the generic type T is only used in output positions. The Add example above would use T in an input position.
To solve this, you have the following options:
Make BaseCollection "covariant" by adding the out keyword, which would require removing any Add methods. This, however, might make your collection kind of useless.
Pass a covariant interface to the method. If you only need to read serverItems, pass an IEnumerable, which is already covariant (and you mention in the comments that BaseCollection already implements IEnumerable):
private List<ClientItem> ConvertToClientItems(IEnumerable<object> serverItems) {
// You can only read serverItems here, so we are fine.
}
make the method itself generic
private List<ClientItem> ConvertToClientItems<T>(BaseCollection<T> serverItems) {
// This also prevents the evil `Add` call, since you'd need to create
// an object of the correct type T first.
}
In BaseCollection, you have to make T covariant by using the "out" keyword.
More information http://msdn.microsoft.com/en-us/library/dd233059.aspx.
(IEnumerable works because it is covariant.)
public interface BaseCollection<out T>

C#: To be XML serializable, types which inherit from IEnumerable must have an implementation of Add(System.Object)

I have the following code:
private static string FindAppointmentsAsXmlString(CalendarView calendar, ExchangeService serv)
{
FindItemsResults<Appointment> appointments = serv.FindAppointments(WellKnownFolderName.Calendar, calendar);
var serializer = new XmlSerializer(appointments.GetType());
var writer = new StringWriter();
try
{
serializer.Serialize(writer, appointments);
Console.WriteLine(writer.GetStringBuilder().ToString());
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.ReadLine();
}
return writer.GetStringBuilder().ToString();
}
When initializing serializer, I get the exception:
To be XML serializable, types which inherit from IEnumerable must have an
implementation of Add(System.Object) at all levels of their inheritance hierarchy.
Microsoft.Exchange.WebServices.Data.FindItemsResults does not implement Add(System.Object).
I've searched around, and I've come to the conclusion that I have to add a public Add(Object obj) method. Now I'm not really sure what this method should contain or when it is called, can anyone point me in the right direction? Does the Add method need to manually add each appointment?
Some links I found helpful:
here
here
Much appreciated.
The Add() method should have a single argument of the type of the elements in the IEnumerable object. For example, if FindItemsResults implements IEnumerable<T> then you can add method void Add(T value). If you want FindItemsResults to be read-only, you could convert FindItemsResults to a List via the ToList() extension method and serialize the list rather than the FindItemsResults object itself.
You need to implement an Add method that can put an object of the type your IEnumerable contains back into the IEnumerable when you deserialize your FindItemsResult and the objects contained yielded by it.
An IEnumerable is not like a List, so a deserialized item cannot generically just be put back into a container of some sort. There is no way to know how one may implement a class that implements IEnumerable, therefor you must explicitly write an Add method for it.
I ran into this same issue when creating a paged result object. The selected answer is basically correct but I thought I would just format it a little nicer and also add a tip of my own.
Basically I implemented the Add, but I have it just throw an exception to guide any future developers that may try to invoke it since as a result set I want to keep it read only. The serializer still works fine so it obviously never invokes Add when serializing. I may run into issues de-serializing but since this object is purely for retrieving a result set all should be good.
Here is what I added to the class that had implemented IEnumerable:
public void Add(T value)
{
throw new NotSupportedException("Add is not supported for paged results. Try adding new items to the repository instead.");
}

From generic Collection to non-generic collection

I working within an older application (from 1.1 days) and there are many non-generic collections like:
[Serializable]
public class MyEntityList : CollectionBase
{
private int _virtualRecordCount;
public int VirtualRecordCount
{
get { return _virtualRecordCount; }
set { _virtualRecordCount = value; }
}
public MyEntityList()
{
}
public MyEntityList(MyEntity[] arr)
{
AddRange(arr);
}
public MyEntityList this[int index]
{
get { return (MyEntity)InnerList[index]; }
}
public void Add(MyEntity item)
{
InnerList.Add(item);
}
etc...
I've upgraded a layer of the application to use a generic Collection<T> for the return type. This layer is auto-generated and the class names are based upon the datasource table names. The business entity classes don't necessary line up either, but not so in this case. In this case, they match perfectly 1:1.
I tried mapping the collections like so:
Collection<MyEntityResponse> responses = GetMyEntityResponses();
AutoMapper.Mapper.CreateMap<MyEntityResponse, MyEntity>();
myEntityList = AutoMapper.Mapper.Map<MyEntityList>(responses);
The strangest thing... I thought that it might squawk at the use of CollectionBase, but I hit F5 anyway. To my suprise, no compiler error and no exception. WOOHOO!
However, later in the app it threw an exception complaining about a type conversion from MyEntityResponse to MyEntity when it tried to perform a foreach() on MyEntityList that was returned from Mapper.Map.
What happened is a new MyEntityList collection was returned but it was filled with MyEntityResponse objects. Huh?? The custom collection overrides the Add() method and specifies that the type must be of type MyEntity. I would expect it to blow up when attempting to add the wrong type to the collection, but it didn't seem to have any issues working with CollectionBase.
So my questions are, if the two types I'm trying to map match perfectly (property to property), and AutoMapper didn't have an issue with CollectionBase, why was it not able to map the enties? And why didn't it throw an exception instead of shoving the wrong type into the collection?
EDIT: I think I know why... because the non-generic collection doesn't have a known type associated with it, like the generic one does.
So, new question... how do I tell it to use MyEntity instead of MyEntityResponse ?
I think I found my answer: http://automapper.codeplex.com/wikipage?title=Lists%20and%20Arrays
For the non-generic enumerable types, only unmapped, assignable types
are supported, as AutoMapper will be unable to "guess" what types
you're trying to map. As shown in the example above, it's not
necessary to explicitly configure list types, only their member types.
As of release 0.2.0, no custom destination collection types are
supported.

Copy constructor versus Clone()

In C#, what is the preferred way to add (deep) copy functionality to a class? Should one implement the copy constructor, or rather derive from ICloneable and implement the Clone() method?
Remark: I wrote "deep" within brackets because I thought it was irrelevant. Apparently others disagree, so I asked whether a copy constructor/operator/function needs to make clear which copy variant it implements.
You should not derive from ICloneable.
The reason is that when Microsoft designed the .net framework they never specified whether the Clone() method on ICloneable should be a deep or shallow clone, thus the interface is semantically broken as your callers won't know whether the call will deep or shallow clone the object.
Instead, you should define your own IDeepCloneable (and IShallowCloneable) interfaces with DeepClone() (and ShallowClone()) methods.
You can define two interfaces, one with a generic parameter to support strongly typed cloning and one without to keep the weakly typed cloning ability for when you are working with collections of different types of cloneable objects:
public interface IDeepCloneable
{
object DeepClone();
}
public interface IDeepCloneable<T> : IDeepCloneable
{
T DeepClone();
}
Which you would then implement like this:
public class SampleClass : IDeepCloneable<SampleClass>
{
public SampleClass DeepClone()
{
// Deep clone your object
return ...;
}
object IDeepCloneable.DeepClone()
{
return this.DeepClone();
}
}
Generally I prefer to use the interfaces described as opposed to a copy constructor it keeps the intent very clear. A copy constructor would probably be assumed to be a deep clone, but it's certainly not as much of a clear intent as using an IDeepClonable interface.
This is discussed in the .net Framework Design Guidelines and on Brad Abrams' blog
(I suppose if you are writing an application (as opposed to a framework/library) so you can be sure no one outside of your team will be calling your code, it doesn't matter so much and you can assign a semantic meaning of "deepclone" to the .net ICloneable interface, but you should make sure this is well documented and well understood within your team. Personally I'd stick to the framework guidelines.)
In C#, what is the preferred way to add (deep) copy functionality to a class?
Should one implement the copy constructor,
or rather derive from ICloneable and implement the Clone() method?
The problem with ICloneable is, as others have mentioned, that it does not specify whether it is a deep or shallow copy, which makes it practically unuseable and, in practice, rarely used. It also returns object, which is a pain, since it requires a lot of casting. (And though you specifically mentioned classes in the question, implementing ICloneable on a struct requires boxing.)
A copy constuctor also suffers from one of the problems with ICloneable. It isn't obvious whether a copy constructor is doing a deep or shallow copy.
Account clonedAccount = new Account(currentAccount); // Deep or shallow?
It would be best to create a DeepClone() method. This way the intent is perfectly clear.
This raises the question of whether it should be a static or instance method.
Account clonedAccount = currentAccount.DeepClone(); // instance method
or
Account clonedAccount = Account.DeepClone(currentAccount); // static method
I slightly prefer the static version sometimes, just because cloning seems like something that is being done to an object rather than something the object is doing. In either case, there are going to be issues to deal with when cloning objects that are part of an inheritence hierarchy, and how those issues are delt with may ultimately drive the design.
class CheckingAccount : Account
{
CheckAuthorizationScheme checkAuthorizationScheme;
public override Account DeepClone()
{
CheckingAccount clone = new CheckingAccount();
DeepCloneFields(clone);
return clone;
}
protected override void DeepCloneFields(Account clone)
{
base.DeepCloneFields(clone);
((CheckingAccount)clone).checkAuthorizationScheme = this.checkAuthorizationScheme.DeepClone();
}
}
I recommend using a copy constructor over a clone method primarily because a clone method will prevent you from making fields readonly that could have been if you had used a constructor instead.
If you require polymorphic cloning, you can then add an abstract or virtual Clone() method to your base class that you implement with a call to the copy constructor.
If you require more than one kind of copy (ex: deep/shallow) you can specify it with a parameter in the copy constructor, although in my experience I find that usually a mixture of deep and shallow copying is what I need.
Ex:
public class BaseType {
readonly int mBaseField;
public BaseType(BaseType pSource) =>
mBaseField = pSource.mBaseField;
public virtual BaseType Clone() =>
new BaseType(this);
}
public class SubType : BaseType {
readonly int mSubField;
public SubType(SubType pSource)
: base(pSource) =>
mSubField = pSource.mSubField;
public override BaseType Clone() =>
new SubType(this);
}
There is a great argument that you should implement clone() using a protected copy constructor
It is better to provide a protected (non-public) copy constructor and invoke that from the clone method. This gives us the ability to delegate the task of creating an object to an instance of a class itself, thus providing extensibility and also, safely creating the objects using the protected copy constructor.
So this is not a "versus" question. You may need both copy constructor(s) and a clone interface to do it right.
(Although the recommended public interface is the Clone() interface rather than Constructor-based.)
Don't get caught-up in the explicit deep or shallow argument in the other answers. In the real world it is almost always something in-between - and either way, should not be the caller's concern.
The Clone() contract is simply "won't change when I change the first one". How much of the graph you have to copy, or how you avoid infinite recursion to make that happen shouldn't concern the caller.
Implementing ICloneable's not recommended due to the fact that it's not specified whether it's a deep or shallow copy, so I'd go for the constructor, or just implement something yourself. Maybe call it DeepCopy() to make it really obvious!
You'll run into problems with copy constructors and abstract classes. Imagine you want to do the following:
abstract class A
{
public A()
{
}
public A(A ToCopy)
{
X = ToCopy.X;
}
public int X;
}
class B : A
{
public B()
{
}
public B(B ToCopy) : base(ToCopy)
{
Y = ToCopy.Y;
}
public int Y;
}
class C : A
{
public C()
{
}
public C(C ToCopy)
: base(ToCopy)
{
Z = ToCopy.Z;
}
public int Z;
}
class Program
{
static void Main(string[] args)
{
List<A> list = new List<A>();
B b = new B();
b.X = 1;
b.Y = 2;
list.Add(b);
C c = new C();
c.X = 3;
c.Z = 4;
list.Add(c);
List<A> cloneList = new List<A>();
//Won't work
//foreach (A a in list)
// cloneList.Add(new A(a)); //Not this time batman!
//Works, but is nasty for anything less contrived than this example.
foreach (A a in list)
{
if(a is B)
cloneList.Add(new B((B)a));
if (a is C)
cloneList.Add(new C((C)a));
}
}
}
Right after doing the above, you start wishing you'd either used an interface, or settled for a DeepCopy()/ICloneable.Clone() implementation.
The problem with ICloneable is both intent and consistency. It's never clear whether it is a deep or shallow copy. Because of that, it's probably never used in only one manner or another.
I don't find a public copy constructor to be any clearer on that matter.
That said, I would introduce a method system that works for you and relays intent (a'la somewhat self documenting)
If the object you are trying to copy is Serializable you can clone it by serializing it and deserializing it. Then you don't need to write a copy constructor for each class.
I don't have access to the code right now but it is something like this
public object DeepCopy(object source)
{
// Copy with Binary Serialization if the object supports it
// If not try copying with XML Serialization
// If not try copying with Data contract Serailizer, etc
}
It is dependent on copy semantics of the class in question, which you should define yourself as the developer. Chosen method is usually based on intended use cases of the class. Maybe it will make a sense to implement both methods. But both share similar disadvantage - it is not exactly clear which copying method they implement. This should be clearly stated in documentation for your class.
For me having:
// myobj is some transparent proxy object
var state = new ObjectState(myobj.State);
// do something
myobject = GetInstance();
var newState = new ObjectState(myobject.State);
if (!newState.Equals(state))
throw new Exception();
instead of:
// myobj is some transparent proxy object
var state = myobj.State.Clone();
// do something
myobject = GetInstance();
var newState = myobject.State.Clone();
if (!newState.Equals(state))
throw new Exception();
looked as clearer statement of intent.
I think there should be a standard pattern for cloneable objects, though I'm not sure what exactly the pattern should be. With regard to cloning, it would seem there are three types of classes:
Those that explicitly support for deep cloning
Those that where memberwise cloning will work as deep cloning, but which neither have nor need explicit support.
Those which cannot be usefully deep cloned, and where memberwise cloning will yield bad results.
So far as I can tell, the only way (at least in .net 2.0) to get a new object of the same class as an existing object is to use MemberwiseClone. A nice pattern would seem to be to have a "new"/"Shadows" function Clone which always returns the present type, whose definition is always to call MemberwiseClone and then call a protected virtual subroutine CleanupClone(originalObject). The CleanupCode routine should call base.Cleanupcode to handle the base type's cloning needs and then add its own cleanup. If the cloning routine has to use the original object, it would have to be typecast, but otherwise the only typecasting would be on the MemberwiseClone call.
Unfortunately, the lowest level of class that was of type (1) above rather than type (2) would have to be coded to assume that its lower types would not need any explicit support for cloning. I don't really see any way around that.
Still, I think having a defined pattern would be better than nothing.
Incidentally, if one knows that one's base type supports iCloneable, but does not know the name of the function it uses, is there any way to reference the iCloneable.Clone function of one's base type?
If you read through all the interesting answers and discussions, you might still ask yourself how exactly you copy the properties - all of them explicitly, or is there a more elegant way to do it? If that is your remaining question, take a look at this (at StackOverflow):
How can I “deeply” clone the properties of 3rd party classes using a generic extension method?
It describes how to implement an extension method CreateCopy() which creates a "deep" copy of the object including all properties (without having to copy property by property manually).

Using type object as returning type - bad practice?

I have a method
private object SetGrid(IGrid grid)
{
grid.PagerHelper.SetPage(1, 10);
grid.SortHelper.SetSort(SortOperator.Ascending);
grid.PagerHelper.RecordsPerPage = 10;
return grid;
}
which returns an object of type object.
Then I cast the object back to the previous type.
var projectModel = new ProjectModel();
projektyModel = (ProjectModel)SetGrid(projectModel);
The gain of this is, the method SetGrid can be reused across the app.
Is this a common practice or should I avoid doing this ?
You could use a generic method instead, and constrain the type argument to your IGrid interface:
private T SetGrid<T>(T grid) where T : IGrid
{
grid.PagerHelper.SetPage(1, 10);
grid.SortHelper.SetSort(SortOperator.Ascending);
grid.PagerHelper.RecordsPerPage = 10;
return grid;
}
You should still be able to call the method in exactly the same way, just without the cast. Type inferencing should be capable of automagically figuring out the required generic type argument for you:
var projectModel = new ProjectModel();
projektyModel = SetGrid(projectModel);
EDIT...
As other answers have mentioned, if your IGrid objects are reference types then you don't actually need to return anything at all from your method. If you pass a reference type then your method will update the original object, not a copy of it:
var projectModel = new ProjectModel(); // assume that ProjectModel is a ref type
projektyModel = SetGrid(projectModel);
bool sameObject = object.ReferenceEquals(projectModel, projektyModel); // true
Since you are passing in an object of a class that implements IGrid you could just as well change the return type to IGrid.
Also, since it's a reference type you don't even need to return the grid again. You could just as well use this:
var projectModel = new ProjectModel();
SetGrid(projectModel);
This is better accomplished with generics. You can use a constraint on the generic typeparam to preserve your type safety!
private T SetGrid<T>(T grid) where T : IGrid
{
grid.PagerHelper.SetPage(1, 10);
grid.SortHelper.SetSort(SortOperator.Ascending);
grid.PagerHelper.RecordsPerPage = 10;
return grid;
}
and then
var projectModel = new ProjectModel();
projectModel = SetGrid(projectModel);
Here, the generic typeparam "T" is actually inferred by the compiler by the way you call the method.
It's worth noting that in the particular use-case you've demonstrated, returning grid is probably unnecessary, as your original variable reference will be appropriately modified after the method call.
In the case you illustrate above there is no need to return grid. The IGrid instance is passed by reference, so your projectModel reference will be updated with the changes you've made in the SetGrid method.
If you still want to return the argument, at least return IGrid, since it is already known that the argument is an IGrid.
In general, provide as much type information as you can when programming in a statically typed language/manner.
"Is this a common practice or should I avoid doing this ?"
This is not common practice. You should avoid doing this.
Functions that only modify the parameter passed in should not have return types. If causes a bit of confusion. In the current C# you could make the modifying function an extention method for better read-ability.
It causes an unnecisary cast of the return type. It's a performance decrease, which may not be noticable... but its still needless since you are casting from an interface, return that interface even if the object is different from the parameter passed in.
Returning object is confusing to users of the function. Lets say the function created a copy and returned a copy... you would still want to return the interface passed in so that people using the function know "hey i'm getting an IGrid back." instead of having to figure out what type is being returned on thier own. The less you make your team mates think about stuff like this the better, for you and them.
This is a very weird example because SetGrid doesn't seem to do a lot of things other than setting some defaults. You are also letting the code perform manipulation on the object that could very well do that by itself. Meaning IGrid and ProjectModel could be refactored to this:
public interface IGrid {
// ...
public void setDefaults();
// ...
}
public class ProjectModel : IGrid {
// ...
public void setDefaults() {
PagerHelper.SetPage(1, 10);
SortHelper.SetSort(SortOperator.Ascending);
PagerHelper.RecordsPerPage = 10;
}
// ...
}
Using this refactoring you only need perform the same with this:
myProjectModel.setDefaults();
You could also create an abstract base class that implements IGrid that implements the setDefaults() method and let ProjectModel extend the abstract class.
what about the SOLID principles ? Concretely the Single Responsibility Principle. The class is in the first place something like a DTO. – user137348
I'm exercising the Interface Segregation Principle out of the SOLID principles here, to hide the implementation from the client of the class. I.e. so the client doesn't have to access the internals of the class it is using or else it is a violation of Principle of Least Knowledge.
Single Responsibility Principle (SRP) only tells that a class should only have one reason to change which is a very vague restriction since a change can be as narrow and broad as you want it to be.
I believe it is okay to put some configuration logic in a parameter class if it is small enough. Otherwise I'd put it all in a factory class. The reason I suggest this solution is because IGrid seems to have reference to PagerHelper and SortHelper that seem to be mutators for IGrid.
So I find it odd that you mention the class being a DTO. A DTO from a purist sense shouldn't have logic in it other than accessors (i.e. getter methods) which makes it strange that ProjectModel itself has references to PagerHelper and SortHelper which I assume can mutate it (i.e. they're setters). If you really want SRP the "helpers" should be in a factory class that creates the IGrid/ProjectModel instance.
Your grid is an IGrid, why not return IGrid?

Categories