Internal class masked by object - c#

Assume that class (B)'s public function has the return line:
return (object)(new List<A>{Some elements})
where A is an internal and sealed class. I cannot change the code of A or B.
After I call this function in B, how do I find the first element of that list. C# does not let me cast that list back into List<A> because A is internal.

Just because you can read the source code or disassemble the code, you should not rely on the current implementation, rather try to use the public interface.
List<A> implements the non-generic IList, so you can cast back to IEnumerable or IList if you really look for trouble.

You can cast a generic List to the non-generic IEnumerable, iterate over that, and then use Object.ToString() to get information about the B instances, or you can just return the reference.
Object obj = new List<string> () { "dd", "ee" };
IEnumerable enumerable = obj as IEnumerable;
bool foundSomething = false;
foreach (var thing in enumerable)
{
if(!foundSomething)
{
// Console.Write(thing.ToString()); If you want
foundSomething = true;
return thing;
}
}

Perhaps I'm misunderstanding the question here, but if A is sealed, you can still write an extension method to iterate or handle the list.
Extension methods for sealed class in c#

You can use interface covariance to cast to IEnumerable<object> and then use some of LINQ's extension methods:
var aItems = (IEnumerable<object>) B.Foo();
Console.WriteLine(aItems.First());

To get first element without touching anything you can do this:
object result = b.MethodThatReturnsList();
object firstEl = ((IList)result)[0];
Problem is that firstElvariable can only be object and you can't cast it to A because it is not accessible. Not very helpful though.
Here is the real problem: you can't declare public methods that return some private/internal types. You will get this compilation error.
Solution is to design a public interface that A will implement and return List<IYourInterface>. Another option is to have public base class.

Related

Casting a collection's generics implicitly

Last night I learned about this wonderful operation of casting by example: a very cool way to generate a collection of some Type using a reference to an existing instance.
My problem is that although this works when you explicitly create the instance, the Type of collection produced is inaccurate if you use activator to instantiate from a Type.
class TestCollectionContent
{
public int id { get; private set; }
}
[Test]
public void TestListCastCreation()
{
var explicitCast = new TestCollectionContent (); //This casts as TestCollectionContent
var explicitList = MakeList (explicitCast); //This casts as List<CommandWithExecute>
explicitList.Add (new TestCollectionContent ());
Type clazz = typeof(TestCollectionContent);
var implicitCast = Activator.CreateInstance (clazz);//This casts as TestCollectionContent
var implicitList = MakeList (implicitCast); //This casts as List<object>
implicitList.Add (new TestCollectionContent ());
Assert.AreEqual (explicitCast.GetType (), implicitCast.GetType ()); //Succeeds
Assert.AreEqual (explicitList.GetType (), implicitList.GetType ()); //FAILS!
}
public static List<T> MakeList<T>(T itemOftype)
{
List<T> newList = new List<T>();
return newList;
}
For my purpose it is imperative that the collection be correctly cast. Any thoughts?
Note that I'm using C# with Unity3D (which uses something akin to .Net 3.5).
Activator.CreateInstance always returns an object, so you will not get any static type information from it when using it. This will make the variable implicitCast of type object although its value is of a more specialized type.
Now when using generics, only the type that is available for static typing is taken into account. So when passing implicitCast to MakeList, all that method sees is an object. As such, the method will be called as MakeList<object> and will return a List<object>, which is of course not of the same type as explicitList.
Unfortunately (or fortunately?) you cannot really do this any better. Generics are supposed to be something for use in a static typing environment, and if you start to create types dynamically, you will lose this ability.
You could however use Activator.CreateInstance for the list creation just as well by doing something like this:
public static IList MakeList(object itemOftype)
{
Type listType = typeof(List<>).MakeGenericType(itemOfType.GetType());
return (IList) Activator.CreateInstance(listType);
}
Of course, this will also just return an object, so you will have to cast it to a more specialized type, or use the non-generic IList interface to have at least some access to it.
This code behaves this way because T is inferred at compile time, not run time. Since implicitCast is of type object, it compiles with MakeList<object>.
var implicitList = MakeList (implicitCast); // equivalent to
List<object> implicitList = MakeList<object>(implicitCast);
var explicitList = MakeList (explicitCast); // equivalent to
List<TestCollectionContent> explicitList =
MakeList<TestCollectionContent>(explicitCast);
If you want it to use the runtime type, you can use reflection or dynamic.

Producing an abstract collection from an abstract collection

This issue has been bugging me for a while. Abstractly speaking, regardless of language, there are often situations when you want to have a method like this:
Collection method(Collection c) {
// select some elements from c based on some filter
// and return a new collection
}
Now, Collection is in this case some abstract class (Like say IList in C# or List in Java) with several implementations. I've been wondering what exactly is the right procedure to produce the abstract collection?
Is it ok to create a concrete collection inside the method and return it? Like:
Collection method(Collection c) {
Collection cc = new ConcreteCollection();
// select some elements from c based on some filter
return cc;
}
This of course puts a constraint on the resulting collection and will produce problems in case, for some reason, we want to cast the result of the method to a different concrete collection than the one used inside the method.
Or, use reflection to determine the actual concrete type of c and create an instance of that class:
Collection method(Collection c) {
Collection cc = c.getClass().newInstance();
// select some elements from c based on some filter
return cc;
}
For some reason this does not seem very "elegant" to me. I would greatly appreciate some insight in this matter.
(Speaking for java). The reason you're returning Collection (an interface) rather than a concrete type (such as ArrayList) is that you're telling the user that they shouldn't care about what the actual concrete type being used is. This leaves you free to choose the appropriate type for your library/api.
If you're enforcing a particular concrete class, then you should be returning that concrete class, rather than the interface.
So, they shouldn't be casting your return type to anything else other than Collection. See
When should I return the Interface and when the concrete class?.
In Java, there are actually some good examples of how to do this in the java.util.Collections class. Instead of taking a Collection and returning a Collection, the key methods take two collections, the "src" and the "dest". For example, Look at the signature of the copy method:
public static <T> void copy(List<? super T> dest, List<? extends T> src)
This puts the responsibility of instantiating the destination list on the caller.
I think you could do the same thing when you want to create a method that acts on a src Collection and puts the results into a destination Collection (rather than Lists).
I agree with Matthew Farwell's answer that you probably just want to return the interface and utilize that, but for the times when you really do need to work with a specific implementing class you can do it the same way the Collections class does it.
One approach you could take is to create a Collection implementation that delegates calls through to the original Collection. This defers the potentially expensive operation of filtering a large Collection until you need to explicitly read elements. It also saves memory.
Example
public interface Filter<T> {
boolean include(T t);
}
public class FilterCollection<T> implements Collection<T> {
private final Collection<T> orig;
private final Filter<T> filter;
public FilterCollection(Collection<T> orig, Filter<T> filter) {
this.orig = orig;
this.filter = filter;
}
public int size() {
int sz = 0;
for (T t : orig) {
if (filter.include(t)) {
++sz;
}
}
return sz;
}
public boolean contains(Object o) {
return o instanceof T && filter.include((T) o) && orig.contains(o);
}
public boolean add(T t) {
if (!filter.include(t)) {
throw new IllegalArgumentException("Element lies outside filter bounds.");
}
orig.add(t);
}
}
The caller should assume a given type of Collection is returned.
Instead it should either copy to the desired type or pass the desired type.
e.g.
Set<T> set2 = new HashSet<T>(filter(set));
List<T> list2 = new ArrayList<T>(filter(list));
or
filter(set2, set); // the target collection is passed.
filter(list2, list);
To the question about ConcreteCollection, it is definitely allowable.
To the concern about having a different concrete collection expected, there are a few ways to go around the problem:
Change the return type of the method. Example:
ConcreteCollection method(Collection c){
ConcreteCollection cc=new ConcreteCollection
for(Object x: c){
//do something
}
return cc
}
Make use of polymorphism. Example:
Collection x=method(c)
x.add(new Object) //add is a method defined within the abstract Collection
Use some utilities to cast the type. Example:
LinkedList h=Collections.toLinkedList(method(c))
Hoped my answer helped. ^^
As far as I can understand, you want to know how to make a method that accepts generic list and returns another modified generic list.
So, my advice will be to use an abstract type that implements method to modify its state.
IList<object> list = new List<object>();
list.Add(new object());
list.Remove(obj);
Or as showed above, instantiate a list that implements IList (or the Java equivalent) work with this instance and return the result as a IList
Edit
If you want to filter some item from a list to a new one, generics can help (I don't know if this feature exists in Java).
public IList<T> Filter<T>(IList<T> list)
{
var result = new List<T>();
result.Add(list[0]); // Or whatever filtering method
return result;
}
If you want your method to accept as many different collection types as possible, and you want to be sure that the result is the same implementation type as what you put in, you might want to use a void method which directly modifies the supplied collection. For instance:
import com.google.common.base.Predicate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class Testy {
private static <T> void filter(Iterable<T> collection, Predicate<T> filter) {
Iterator<T> iterator = collection.iterator();
while (iterator.hasNext()) {
if (!filter.apply(iterator.next())) { // Condition goes here
iterator.remove();
}
}
}
public static void main(String... args) {
List<String> list = new ArrayList<String>();
list.addAll(Arrays.asList("A", "B", "C", "D"));
filter(list, new Predicate<String>() { // Anonymous filter (predicate)
#Override public boolean apply(String input) {
return input.equals("B");
}
});
System.out.println(list); // Prints ["B"]
}
}
The helper method filter takes an Iterable, the simplest type required for iterating over something. Apply the filter to each element, and if the predicate (filter) returns false, remove that element from the underlying collection with Iterator.remove().
The Predicate<T> interface here comes from Google. You can easily write your own if you don't wish to import it. The only required method is apply(T) which returns a boolean. Either that, or just write your condition directly inside the loop and get rid of the second parameter.
This method is the most efficient if your original collection is mutable and you don't wish to keep any intermediate results.
Another option is to use Google Collections Collections2.filter(Collection<E>, Predicate<E>) which returns a Collection<E> just like in your question. Similarly, the Iterables class will do the same thing, but create lazy iterables where the filters are only applied when actually doing the iterating.

SomeList<T> : List<T> can't be cast as List<T>?

See comment in Main(). Why can't I perform the following?
public class SomeList<T> : List<T>
{
public SomeList(List<T> existing)
{
foreach (var item in existing)
Add(item);
}
public override string ToString()
{
return "I'm a better list.";
}
}
internal interface IReadStuff<T>
{
List<T> ReadStuff();
}
public class ReaderStrategy<Foo> : IReadStuff<Foo>
{
public List<Foo> ReadStuff()
{
return new List<Foo>();
}
}
public class Foo {}
public class Main
{
public Main()
{
var reader = new ReaderStrategy<Foo>();
// This works, but type is List<Foo>, not SomeList<Foo>
List<Foo> aList = reader.ReadStuff();
// This does not compile, but is what I want to do:
SomeList<Foo> aBetterList = reader.ReadStuff();
// This compiles, but always generates null for aBetterList:
SomeList<Foo> anotherBetterList = reader.ReadStuff() as SomeList<Foo>;
// This is funky but works:
SomeList<Foo> works = new SomeList<Foo>(reader.ReadStuff());
}
}
I am struggling understanding how to use generics with inherited types. I have a need for the above because I want to extend the functionality of List<T> is some special way, for example see SomeList<T> overrides ToString(). However, I want to keep my factory strategy using .Net generic List<T>. Is there a way to make this work?
Edit
I added a constructor that accepts List<T> and adds to SomeList<T>. This doesn't seem natural, but works. This is an expensive operation, especially if List<T> is large.
My question title was not the best, what I was striving for was an example showing a better way to do this.
reader.ReadStuff() returns List<Foo> - but you are trying to assign it to an object of type SomeList<Foo> which inherits from List<Foo>. This doesn't work because List<Foo> is not a SomeList<Foo> - it's the other way round.
Think about it - it is legal to return a List<Foo> object from ReadStuff() - then you are trying to access functionality on this object that is only available on SomeList<Foo> - this will break and that's why OOP doesn't allow you to do this - instances of a child class can be used where an instance of a parent class is expected - but you cannot use a parent class where a child class is expected.
Going back to your question title: SomeList<T> : List<T> can't be cast as List<T>? Yes that's possible, but you are trying to cast List<T> to SomeList<T>.
All instances of SomeList are instances of List. However, not all instances of List are instances of SomeList. That is what the second assignment is doing. reader.ReadStuff() returns a List, not a SomeList. Hope this helps.
In your example, you're not casting an instance of SomeList<Foo> to List<Foo>, you're trying to cast a List<Foo> to a SomeList<Foo>. You're going from less specific to more specific, which doesn't work. It should work the other way around.
change this code
SomeList<Foo> aBetterList = reader.ReadStuff()
to
SomeList<Foo> aBetterList = reader.ReadStuff() as SomeList<Foo>;
before using
if(aBetterList !=null) {}

how List<T> does not implement Add(object value)?

I believe it's pretty stupid, and I am a bit embarrassed to ask this kind of question, but I still could not find the answer:
I am looking at the class List<T> , which implemetns IList.
public class List<T> : IList
one of the methods included in Ilist is
int Add(object value)
I understand that List<T> should not expose that method (type safety...), and it really does not. But how can it be? mustnt class implement the entire interface?
I believe that this (interface) method is implemented explicitly:
public class List<T> : IList
{
int IList.Add( object value ) {this.Add((T)value);}
}
By doing so, the Add( object ) method will by hidden. You'll only able to call it, if you cast the List<T> instance back to an IList instance.
A quick trip to reflector shows that IList.Add is implemented like this:
int IList.Add(object item)
{
ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(item, ExceptionArgument.item);
try
{
this.Add((T) item);
}
catch (InvalidCastException)
{
ThrowHelper.ThrowWrongValueTypeArgumentException(item, typeof(T));
}
return (this.Count - 1);
}
In other words, the implementation casts it to T to make it work and fails it you pass a non T compatible type in.
List<T> explicitly implements IList.Add(object value) which is why it's not typically visible. You can test by doing the following:
IList list = new List<string>();
list.Add(new SqlDataReader()); // valid at compile time, will fail at runtime
It implements it explicitly, so you have to cast to IList first to use it.
List<int> l = new List<int>();
IList il = (IList)l;
il.Add(something);
You can call it be casting your list instance to the interface first:
List<int> lst = new List<int>();
((IList)lst).Add("banana");
And you'll get as nice, runtime, ArgumentException.
Frederik is right that List<T>'s implementation of IList is explicit for certain members, particularly those that pose a threat to type safety.
The implementation he suggests in his answer can't be right, of course, since it wouldn't compile.
In cases like this, the typical approach is to make a valiant effort to try to get the interface member to work, but to give up if it's impossible.
Note that the IList.Add method is defined to return:
The position into which the new
element was inserted, or -1 to
indicate that the item was not
inserted into the collection.
So in fact, a full implementation is possible:
int IList.Add(object value)
{
if (value is T)
{
Add((T)value);
return Count - 1;
}
return -1;
}
This is just a guess, of course. (If you really want to know for sure, you can always use Reflector.) It may be slightly different; for example it could throw a NotSupportedException, which is often done for incomplete interface implementations such as ReadOnlyCollection<T>'s implementation of IList<T>. But since the above meets the documented requirements of IList.Add, I suspect it's close to the real thing.

How to allow iteration over a private collection but not modification?

If I have the following class member:
private List<object> obs;
and I want to allow traversal of this list as part of the class' interface, how would I do it?
Making it public won't work because I don't want to allow the list to be modified directly.
You would expose it as an IEnumerable<T>, but not just returning it directly:
public IEnumerable<object> Objects { get { return obs.Select(o => o); } }
Since you indicated you only wanted traversal of the list, this is all you need.
One might be tempted to return the List<object> directly as an IEnumerable<T>, but that would be incorrect, because one could easily inspect the IEnumerable<T> at runtime, determine it is a List<T> and cast it to such and mutate the contents.
However, by using return obs.Select(o => o); you end up returning an iterator over the List<object>, not a direct reference to the List<object> itself.
Some might think that this qualifies as a "degenerate expression" according to section 7.15.2.5 of the C# Language Specification. However, Eric Lippert goes into detail as to why this projection isn't optimized away.
Also, people are suggesting that one use the AsEnumerable extension method. This is incorrect, as the reference identity of the original list is maintained. From the Remarks section of the documentation:
The AsEnumerable<TSource>(IEnumerable<TSource>) method has no effect other than to change the compile-time type of source from a type that implements IEnumerable<T> to IEnumerable<T> itself.
In other words, all it does is cast the source parameter to IEnumerable<T>, which doesn't help protect referencial integrity, the original reference is returned and can be cast back to List<T> and be used to mutate the list.
You can use a ReadOnlyCollection or make a copy of the List and return it instead (considering the performance penalty of the copy operation). You can also use List<T>.AsReadOnly.
This has already been said, but I don't see any of the answers as being superclear.
The easiest way is to simply return a ReadOnlyCollection
private List<object> objs;
public ReadOnlyCollection<object> Objs {
get {
return objs.AsReadOnly();
}
}
The drawback with this is, that if you want to change your implementation later on, then some callers may already be dependent on the fact, that the collection provides random access. So a safer definition would be to just expose an IEnumerable
public IEnumerable<object> Objs {
get {
return objs.AsReadOnly();
}
}
Note that you don't have to call AsReadOnly() to compile this code. But if you don't, the caller my just cast the return value back to a List and modify your list.
// Bad caller code
var objs = YourClass.Objs;
var list = objs as List<object>;
list.Add(new object); // They have just modified your list.
The same is potential problem also exists with this solution
public IEnumerable<object> Objs {
get {
return objs.AsEnumerable();
}
}
So I would definately recommend that you call AsReadOnly() on you list, and return that value.
To your Interface add the following method signature:
public IEnumerable TraverseTheList()
Implimented as so:
public IEnumerable<object> TraverseTheList()
{
foreach( object item in obj)
{
yield return item;
}
}
that will allow you to do the following:
foreach(object item in Something.TraverseTheList())
{
// do something to the item
}
The yield return tells the compiler to build an enumerator for you.
You can do this in two ways:
Either By converting the list into a Readonly collection:
new System.Collections.ObjectModel.ReadOnlyCollection<object>(this.obs)
Or by returning an IEnumerable of the items:
this.obs.AsEnumerable()
Expose a ReadOnlyCollection<T>
Interesting post and dialog on this very issue: http://davybrion.com/blog/2009/10/stop-exposing-collections-already/.
Have you considered deriving a class from System.Collections.ReadOnlyCollectionBase?
Just return an IReadOnlyCollection.
private List<object> obs;
IReadOnlyCollection<object> GetObjects()
{
return obs;
}

Categories