Solved

Casting generic collection containing interface.

Posted on 2010-09-03
10
576 Views
Last Modified: 2012-08-13
I have some objects that are cacheable.  The interface looks like this:

public interface ICacheable {
    string EntityTag { get; }
}

One of the classes that implement it look like this:

public class User : ICacheable {
     public int Id { get; }
     public int Version { get; }

     public string EntityTag { get { return String.Format("{0}-{1}", Id, Version); } }
}

Now, I have a method that returns a readonly collection of users (System.Collections.ObjectModel.ReadOnlyCollection<User>) and I need to pass this to a method that only accepts a readonly collection of ICacheable objects.  I would think that the compiler would handle this kind of cast, but it isn't working.

It boils down to why won't this work:

public System.Collections.ObjectModel.ReadOnlyCollection<ICacheable> GetUsers() {
   ReadOnlyCollection<Users> userList = DataManager.GetUsers();

   return userList;
}
0
Comment
Question by:ChetOS82
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 4
10 Comments
 
LVL 8

Expert Comment

by:Gururaj Badam
ID: 33597933
When you say it isn't working what exactly is happening?
0
 
LVL 18

Author Comment

by:ChetOS82
ID: 33597949
Error: Cannot implicitly convert type ReadOnlyCollection<User> to ReadOnlyCollection<ICacheable>.

If I try to explictly cast, I get the same error without the word "implicitly".
0
 
LVL 8

Expert Comment

by:Gururaj Badam
ID: 33598050
public System.Collections.ObjectModel.ReadOnlyCollection<ICacheable> GetUsers() {
   ReadOnlyCollection<ICloneable> userList = DataManager.GetUsers();

   return userList;
}

Observe the userList declaration
0
Resolve Critical IT Incidents Fast

If your data, services or processes become compromised, your organization can suffer damage in just minutes and how fast you communicate during a major IT incident is everything. Learn how to immediately identify incidents & best practices to resolve them quickly and effectively.

 
LVL 18

Author Comment

by:ChetOS82
ID: 33598082
Not sure what you are getting at.  1) DataManager.GetUsers returns a ReadonlyCollection<User>, 2) User is not ICloneable (if I use ICacheable instead, I still get invalid cast error).
0
 
LVL 16

Accepted Solution

by:
kris_per earned 450 total points
ID: 33598093

Try the Cast method of ReadOnlyCollection/IEnumerable for this (with LINQ)

ReadOnlyCollection<User> users;

IEnumerable<ICacheable> clist = users.Cast<ICacheable>();
0
 
LVL 8

Expert Comment

by:Gururaj Badam
ID: 33598096
Since you're a base type (interface) it's good to replace all references with ICloneable include your GetUsers unless it's not your code.
0
 
LVL 18

Author Comment

by:ChetOS82
ID: 33598141
When you say ICloneable, do you mean ICacheable?  I cannot replace the return of DataManager.GetUsers() because other code in the system doesn't care that the User object is ICacheable.

@kris_per: Is that essentially the same as this:
List<ICacheable> cacheableUsers = new List<ICacheable>();
foreach (ICacheable user in userList) {
     cacheableUsers.Add(user);
}
return new ReadOnlyCollection<ICacheable>(cacheableUsers);

That was what I used as a workaround.  I was hoping that C# could handle the cast implicily.  If not, I'll replace this code with the Cast call you recommended.
0
 
LVL 8

Assisted Solution

by:Gururaj Badam
Gururaj Badam earned 50 total points
ID: 33598177
The problem you're seeing is CoVariance/ContraVariance. This has been addressed in 4.0.
0
 
LVL 8

Expert Comment

by:Gururaj Badam
ID: 33598282
0
 
LVL 18

Author Comment

by:ChetOS82
ID: 33598284
I realize that this is an issue of covariance, but I was hoping that someone knew if I was just looking at this wrong.  Apparently covariance is supported everywhere except with Generics.  So, in C# 4 I will be able to do this implicitly.

Some points to Novice for giving the problem a name, most points to kris_per for validation.

I ended up writting a method that can be replaced later.  I prefer it over the Linq Cast<> for two reasons.  1) I don't have Linq referenced in this project, 2) Cast returns an IEnumerable, but I want a ReadOnlyCollection.

public ObjectModel.ReadOnlyCollection<ICacheable> MakeCollectionCacheable<T>(ObjectModel.ReadOnlyCollection<T> list) {
   var cacheableList = new List<ICacheable>(list.Count);
   foreach (ICacheable cacheableObject in list) {
       cacheableList.Add(cacheableObject);
   }
   return new ObjectModel.ReadOnlyCollection<ICacheable>(cacheableList);
}
0

Featured Post

Is Your DevOps Pipeline Leaking?

Is your CI/CD pipeline a hodge-podge of randomly connected tools? You’ve likely got a tool to fix one problem & then a different tool to fix another, resulting in a cluster of tools with overlapping functionality. Learn how to optimize your pipeline with Gartner's recommendations

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

We all know that functional code is the leg that any good program stands on when it comes right down to it, however, if your program lacks a good user interface your product may not have the appeal needed to keep your customers happy. This issue can…
Many of us here at EE write code. Many of us write exceptional code; just as many of us write exception-prone code. As we all should know, exceptions are a mechanism for handling errors which are typically out of our control. From database errors, t…
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question