Using Interface Type as generic - c#

I have a class which must implement the following property
public ICollection<IType> Items
{
get { return this.items;}
}
My question is how to implement this when the type of this.items is a List<MyType> where MyType implements IType. I need to ensure the following:
Unecessary enumeration of the list is avoided if possible
That the class can internally treat the elements of this.items as their concrete type
That external callers may add and remove elements to this collection
Thanks in advance.

How about Items being IEnumerable<IType>? IEnumerable is covariant so the code would just work with no changes. On the other hand, you could have another, dedicated method to add elements to the internal list.
class MainClass
{
public static void Main()
{
ShowMeHowToDoIt show = new ShowMeHowToDoIt();
show.Add( new TheType() );
foreach ( var item in show.Items )
{
Console.WriteLine( item );
}
}
}
public class ShowMeHowToDoIt
{
private List<TheType> items = new List<TheType>();
public void Add( TheType item ) { items.Add( item ); }
public IEnumerable<IType> Items
{
get { return items; }
}
}
public interface IType { }
public class TheType : IType { }

Like Paul mentioned, you can't have both #2 and #3. You'll have to pick one or the other, or expose the concrete type to external callers. But, for your actual requirement, your best bet is to store your collection as a List internally, and just use a method when you need to get a member by the concrete type. Something like this:
private List<IType> items = new List<IType>();
private TType GetItem<TType>(int index)
where TType : IType
{
return (TType)items[index];
}
public ICollection<IType> Items
{
get
{
return this.items;
}
}

As pointed out by #PaulPhillips in the comments to this question:
Requirements (2) and (3) are contradictory.
One approach is to change the type of Items to IEnumerable<IType> and have another property of ICollection<MyType>. This will mean some redesign but clearly I was going about this wrong anyway.
Thanks!

Either declare this.items as a List<IType> if you want to expose it as ICollection<IType> and thus allowing external callers to add ITypes that are not MyTypes.
Internally work like this on the items of the list
var myObj = this.items[i] as MyType;
if (myObj == null) {
work with this.items[i] and treat it as a IType
} else {
work with myObj which is a MyType
}
OR
declare the public property as
public ICollection<MyType> Items { get return this.items; } }
and thus allow external callers to add only items of type MyType.
I am sorry, but you cannot fulfill conditions (2) and (3) at the same time
UPDATE
Another option is to only allow external callers to get items of the list but not to add items, by using an indexer having only a getter.
public IType this[int i]
{
get { return this.items[i]; }
}
an external caller can then access items like this
var obj = new ClassImplementingThisStuff();
int i = 5;
IType x = obj[i];
Also add a count property
public int Count {
get { return this items.Count; }
}
This solution avoids unnecessary enumeration.

I think the points in the comments about this being possibly a bad design are valid, however you can still do something like this and get away with it:
interface IFruit
{
string Name { get; }
string SerialNumber { get; }
}
class Apple : IFruit
{
private string _serial = Guid.NewGuid().ToString();
public string Name {
get {
return "Apple";
}
}
public string SerialNumber {
get { return _serial; }
}
}
class AppleBasket : IEnumerable<IFruit>
{
private List<Apple> _items = new List<Apple>();
public void Add(Apple apple) {
_items.Add(apple);
}
public IEnumerator<IFruit> GetEnumerator() {
return _items.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return _items.GetEnumerator();
}
}
/******************/
AppleBasket basket = new AppleBasket();
Apple apple1 = new Apple();
basket.Add(apple1);
Apple apple2 = new Apple();
basket.Add(apple2);
foreach (IFruit fruit in basket) {
Console.WriteLine(fruit.SerialNumber);
}
I would recommend you rethink your approach though.

Related

Getting an object's list from inside another object

This is the layout
House -> HouseDef -> Room -> Door
L---> Windows
The problem is that any class may or may not have lists and nested classes like HouseDefinition does. The point is it should be flexible to handle any of these three cases for class variations:
1. hasList,
2. hasNestedObject with List inside that Nested Object
3. Has neither a List nor Nested class
Example of 1 being a Room class which contains a Window List
Example of 2 like House Class
Example of 3 like a Window Class
I have these two classes that I want to access generically from another class. I want to be able to get the Rooms List in House Definition by access of House class stored as an object in MyTreeNode. How can I do this not bound by types, or polymorphic to support a deeper hierarchy level in the future?
public class House
{
string name;
HouseDefinition definition;
public string Name() { return name; }
public HouseDefinition Definition {get {return definition;}}
public House(string name,HouseDefinition definition)
{
this.name = name;
this.definition = definition;
}
}
public class HouseDefinition
{
private List<Room> rooms = new List<Room>();
string type;
public List<Room> Rooms { get { return rooms; } }
public Room this[int i] { get { return rooms[i]; } }
public HouseDefinition(string type)
{
DefaultLayout();
this.type = type;
}
}
public class MyTreeNode : TreeNode
{
string label;
IEnumerable items;
bool hasList;
object item;
public string Label { get {return label; } }
public IEnumerable Items { get { return items;} }
public object Item { get { return item; } }
public bool HasList { get { return hasList; } }
public MyTreeNode(object item)
{
this.item = item;
label = item.ToString();
hasList = false;
}
public MyTreeNode(object item, IEnumerable Items)
{
this.item = item;
label = item.ToString();
hasList = true;
}
}
I think your classes look fine, but I would remove HouseDefinition, since those properties just seem like House to me. If you want to practice inheritance, you could create an IBuilding interface that forces House, Mansion, Shack to implement GetRooms() or something like that. A couple other things:
Your TreeNode class should be using generic types like public MyTreeNode(T item)
You should check out autoimplemented properties - the public fields automatically create private backing fields, so you don't need to create a private field and a getter like you did here: public object Item { get { return item; } }
it's considered bad practice to use the "object" type, so you should convert those to the generic types mentioned above
Good luck, your code is looking good so far!

Interface reference that specifies I need an object implementing 2 or more interfaces

Let us say I have this overly simple code here:
class Person
{
public int age;
public string name;
public Person(int age, string name)
{
this.age = age;
this.name = name;
}
}
public class MySimpleDatabase
{
List<Person> people;
internal List<Person> People
{
get
{
if(people == null)
{
people = new List<Person>();
people.Add(new Person(24, "ASD"));
people.Add(new Person(35, "QWE"));
people.Add(new Person(12, "MNB"));
}
return people;
}
}
}
public class ProcessPeopleConcrete
{
public void WriteNames()
{
List<Person> people = new MySimpleDatabase().People;
foreach (var person in people)
{
Console.WriteLine(person.name);
}
}
}
public class ProcessPeopleInterface
{
public void WriteNames()
{
//question for here.
IEnumerable<Person> people = new MySimpleDatabase().People;
foreach (var person in people)
{
Console.WriteLine(person.name);
}
}
}
Here I have the concrete processor as well as the interface based one. Here the interface processor is more maintainable of course, but as far as I know
//edited here to clarify
I can specify only one type for a variable that I require, in my case it is the IEnumerable<Person>.
What if I need something there that implements not one, but two interfaces at the same time, that have nothing to do with each other (one doesn't implement the other)?
So say I need any collection that has to implement both ICloneable and IEnumerator. In a comment it was put correctly that I could define another interface that implements both of them. But if I use pre-defined collections, I can't do that becuase then I won't be able to toss any of them as they obviously don't implement my custom made interface.
What sort of type would I specify in this case to my variable people (commented with "question here")? If there was a variable declaration like <IEnumerable, ICloneable> people; that would imaginarily mean I need something that implements both IEnumerable and ICloneable. But is there a language feature similar to that or it is what I said it is - imaginary only?
As you have figured out, you cannot force classes to implement interfaces which they don't ;)
You have also noted that interfaces are used to solve a specific problem. In one case they solve how collections can be enumerated, and in the other case they solve how an object can be cloned.
From your question I take it that you want to be able to tell that the returned object solves both problems and you wonder how you can tell that in the method contract.
You do it by defining a new interface:
public interface ISuperClonableList<T> : IEnumerable<T>, IClonable
{
}
That's it.
If the list itself isn't clonable you need to wrap it in a new class which implements both interfaces. Pass the actual list as a constructor parameter and call it in every IEnumerable method implementation.
The problem with cloning interfaces is that they typically do not specify if it should be a deep or shallow clone. It's important to know that since it can cause large problems if the contained items are mutable.
Example generated from ReSharper:
public class MyListWrapper<T> : ISuperClonableList<T>
{
private readonly ISuperClonableList<T> _innerList;
public MyListWrapper(ISuperClonableList<T> innerList)
{
_innerList = innerList;
}
public IEnumerator<T> GetEnumerator()
{
return _innerList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable) _innerList).GetEnumerator();
}
public void Add(T item)
{
_innerList.Add(item);
}
public void Clear()
{
_innerList.Clear();
}
public bool Contains(T item)
{
return _innerList.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
_innerList.CopyTo(array, arrayIndex);
}
public bool Remove(T item)
{
return _innerList.Remove(item);
}
public int Count
{
get { return _innerList.Count; }
}
public bool IsReadOnly
{
get { return _innerList.IsReadOnly; }
}
public int IndexOf(T item)
{
return _innerList.IndexOf(item);
}
public void Insert(int index, T item)
{
_innerList.Insert(index, item);
}
public void RemoveAt(int index)
{
_innerList.RemoveAt(index);
}
public T this[int index]
{
get { return _innerList[index]; }
set { _innerList[index] = value; }
}
}
This might not exactly be what you are looking for, but here's something similar to you concept. I created a simple function accepting a Tuple of IEnumerable and IList, then you can feed arguments to it:
public static void Foo(Tuple<IEnumerable<int>, IList<int>> complex)
{
foreach (var item in complex.Item1)
{
Console.WriteLine(item.ToString());
}
complex.Item2.Add(9);
}
A simple list:
List<int> ints = new List<int>
{
1,
3,
5,
7
};
The function is then invoked by either first instantiating a separate variable, as I did, or writing the instantiation right into the Foo() function.
Tuple<IEnumerable<int>, IList<int>> tuple = Tuple.Create((ints as IEnumerable<int>), (ints as IList<int>));
Foo(tuple);
I'm also interested in a real solution though, provided that there is one.

Method with generic return type but not generic input. Is this possible?

Suppose we have a NodeData class:
public class NodeData<T>
{
public string Name;
public T Value;
public NodeData(string name, T value)
{
this.Name = name;
this.Value = value;
}
}
And a base Node class and child classes that have several properties with type NodaData:
public class Node
{
public List<NodeData<T>> listOutputs<T>()
{
var fieldInfos = GetType().GetFields();
var list = new List<NodeData<T>>();
foreach (var item in fieldInfos)
{
Type t = item.FieldType;
string name = item.Name;
if (t == typeof(NodeData<T>))
{
var output = new NodeData<T>(name, default(T));
list.Add(output);
}
}
return list;
}
}
public class TestNode : Node {
public NodeData<int> data;
public NodeData<double> data2;
public NodeData<double> data3;
public TestNode ()
{
data = new NodeData<int>("test", 111);
data2 = new NodeData<double>("test", 113);
}
}
As you can see there is a method which lists all outputs with type T in the Node class So I can find what are the output fields of the child class in runtime:
TestNode node = new TestNode ();
var list = node.listOutputs<int>(); // this returns data
But I need to know how to use this method to list all NodeOutputs of any type T. In this example int and double. Do I need to add a method with this signature public List<NodeData<T>> listOutputs() // should return all properties data, data2, data3. Is it possible to have method like this? return type is generic but there is no type argument for method.
Even after your edit(s) it is not entirely clear what you are trying to achieve but here are my assumptions:
-You want to have some kind of Node object that acts as a container for different types of NodeData elements.
-You want to be able to return one list from this Node object that contains all NodeData elements stored in the Node container, regardless of the NodeData objects' type.
Instead of returning a List> object from the listOutputs methods, just return the non-generic version of the List object. Then you don't have to deal with T in the method call.
The logic that loops through the objects in the non-generic list can then examine the type to process the contained NodeData objects correctly.
Important note: My proposed solution is by no means pretty but I think it answers the question. In my opinion something is already seriously flawed from an OO point of view in the presented code (e.g. use of reflection) and a better solution would have to start by changing the underlying data structures. But that can only be done if we have more information how this is to be used, e.g. what kind of logic consumes the returned list.
You can create a base interface that will be used to return the generic data.
public interface INodeData
{
string Name { get; }
}
public class NodeData<T> : INodeData
{
public string Name { get; private set; }
public T Value { get; private set; }
public NodeData(string name, T value)
{
this.Name = name;
this.Value = value;
}
}
I modified the function to return a list of the interface. Doing this you won't depend on T.
public class Node
{
public List<INodeData> listOutputs()
{
var fieldInfos = GetType().GetFields();
var list = new List<INodeData>();
foreach (var item in fieldInfos)
{
INodeData data = GetType().GetField(item.Name).GetValue(this) as INodeData;
list.Add(data);
}
return list;
}
}
If you test the method, it should return the fields in a list. To work with a specific type, you can make use of is before using the type you search for.
public class TestNode : Node
{
public NodeData<int> data;
public NodeData<double> data2;
public NodeData<double> data3;
public TestNode()
{
data = new NodeData<int>("test", 111);
data2 = new NodeData<double>("test", 113);
}
}
private static void Main(string[] args)
{
TestNode node = new TestNode();
var list = node.listOutputs(); // this returns data
}
This may well be an XY problem, in that you probably want to rethink how you are designing your classes because using reflection in this way doesn't seem right. But give the problem you've presented, I'd tackle it like this:
public abstract class NodeDataBase
{
public string Name { get; set; }
public NodeData(string name)
{
this.Name = name;
}
// this isn't actually needed, but might be helpful
public abstract object GetValue();
}
public class NodeData<T> : NodeDataBase
{
public T Value { get; set; }
public NodeData(string name, T value) : base(name)
{
this.Value = value;
}
public override object GetValue()
{
return Value;
}
}
And now your method signature would be:
public List<NodeDataBase> listOutputs()
And with the list returned, you can use the GetValue method to get the actual values without needing to cast to the right generic type to be able to get at the Value property.
You could also just have a return type of List<object>, but then you'll have to cast each member of that list to the right generic type before you can access it's properties.
You can also avoid that nasty reflection code, instead of having data, data1, and data2, you could simply do this in your Node class:
public class Node
{
public List<NodeDataBase> Data { get; protected set; }
public Node()
{
Data = new List<NodeDataBase>();
}
}
And now you don't even need your listOutputs method because you can just get the list from the node (unless you actually wanted a copy, but that's fairly trivial to implement).
And you TestNode would be just:
public class TestNode : Node {
public TestNode ()
{
Data.Add(new NodeData<int>("test", 111));
Data.Add(new NodeData<double>("test", 113));
}
}

Using LINQ with wrapped arrays

I'm new to LINQ and I'm doing a simple project to learn the features of the technology.
Currently I've got a static class that wraps an array of object (a kind of simple factory). Let's say it looks like the following:
public static class Factory
{
private static Item[] items = new Item[]
{
// items are created here
};
// ...
}
Now I can add some functions to my Factory that allow me to query the inner array, e.g.
public static Item GetByID(ItemID id)
{
var query =
from item in items
where item.ID == id
select item;
return query.First();
}
However, this requires me to modify the internals of the Factory class. Is there a way to write such queries from the 'outer world' instead ?
public class OtherClass
{
var result = from it in Factory select ...
}
?
Yes, you can. Just use linq on the Factory from the 'outer world':
public class OtherClass
{
public Item Get(ItemId id)
{
return Factory.Items.SingleOrDefault(i => i.ID == id);
}
}
Of course, to do this, you'd need to change the access modifier of the items array to be public.
There are so many options.
The easiest thing to do is just to expose a public property that allows just what you want to have allowed:
public static class Factory
{
private static Item[] items = new Item[]
{
// items are created here
};
public static IEnumerable<IReadableItem> Items{ get { return items; } }
// ...
}
The above code assumes that the Item class implements an IReadableItem interface that only has the methods and properties on it that you want to allow people to access. You could also clone the items list before returning it each time, if you're worried someone might re-cast the Items or try to modify it using reflection. Because the standard LINQ methods all work off of IEnumerable<>s, this would allow someone to effectively produce a LINQ query on your items, without exposing overmuch data.
List<string> bestItemNames = Factory.Items.Where(i => i.IsBest)
.Select(i => i.Name)
.ToList();
If you wanted to get really fancy, you could even implement your own LINQ provider. From a language perspective, LINQ expression syntax just maps to specific method names, so if you had a class that implemented a .Where() and a .Select() method, then you could implement that pretty much however you wanted, and people wouldn't know any different until they tried doing something that your methods didn't support.
One possibility is to implement IQueryable<T> for a non-static class:
public class Factory<T> : IQueryable<T>
{
protected T[] _items = new T[]{};
public Type ElementType
{
// or typeof(T)
get { return _items.AsQueryable().ElementType; }
}
public System.Linq.Expressions.Expression Expression
{
get { return _items.AsQueryable().Expression; }
}
public IQueryProvider Provider
{
get { return _items.AsQueryable().Provider; }
}
public IEnumerator<T> GetEnumerator()
{
return ( IEnumerator<T> )_items.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _items.GetEnumerator();
}
}
Derive non-generic class to populate array (if desired)
public class ItemFactory : Factory<Item>
{
public ItemFactory()
{
// items are created here
}
}
Create static instance
public static class Factories
{
private static ItemFactory _itemFactory = new ItemFactory();
public static ItemFactory ItemFactory { get { return _itemFactory; } }
}
Usage:
var specificItem = Factories.ItemFactory
.Where( item => item.ID == id )
.SingleOrDefault();
use an expression tree
public class OtherClass
{
public Item Get(ItemId id)
{
return Factory.Get(i => i.id == id);
}
}
and change the get method to
public Item Get(Expression<Func<Item,bool>> filter)
{
return items.SingleOrDefault(filter);
}
however, this approach makes little sense unless you are encapsulating some other logic in your factory class i.e. select only rows that are not soft deleted.

Return reference to a generic list?

Suppose I have classes set up like this:
public abstract class GenericCustomerInformation
{
//abstract methods declared here
}
public class Emails : GenericCustomerInformation
{
//some new stuff, and also overriding methods from GenericCustomerInformation
}
public class PhoneNumber : GenericCustomerInformation
{
//some new stuff, and also overriding methods from GenericCustomerInformation
}
//and more derivative classes for emails, addresses, etc ..
Then I have this function to return a specific list:
public List<GenericCustomerInformation> GetLists<T>()
{
if (typeof(T) == typeof(Alias))
{
return aliases.Cast<GenericCustomerInformation>().ToList();
}
if (typeof(T) == typeof(PhoneNumber))
{
return phoneNumbers.Cast<GenericCustomerInformation>().ToList();
}
// .. and the same for emails, addresses, etc ..
}
Now suppose I want to add to these lists using just one function:
public void AddToList<T>(T iGenericCustomerInformation)
{
GetLists<T>().Add((T)(object)iGenericCustomerInformation); //Doesn't work as intended. GetLists<T> seems to be returning lists as value, which is why any additions
}
The problem is that AddToList<T> doesn't work as intended. GetLists<T> seems to be returning lists as value, which is why any additions I do are not reflected in the primary list structure ...
So how to return the list as a reference, so that I can use that reference to do list additions through other functions ?
You're already defeating the point of generics by having all those typeof()s and if statements. That's not generic at all. I'd say just put the if statement in your AddToList() method and nix the generics.
public void AddToList(GenericCustomerInformation item)
{
Alias aliasItem = item as Alias;
if(aliasItem != null)
{
aliases.Add(aliasItem);
return;
}
PhoneNumber phoneNumberItem = item as PhoneNumber;
if(phoneNumberItem != null)
{
phoneNumbers.Add(phoneNumberItem);
}
}
Why not keep all your lists in a dictionary of lists ?
private Dictionary<Type, List<GenericCustomerInformation>> MyLists;
public List<GenericCustomerInformation> GetLists<T>()
{
return MyLists[typeof(T)];
}
public void AddToLists<T>(GenericCustomerInformation item)
{
GetLists<T>().Add(item);
}

Categories