Working with a hashtable of unknown but similar objects (C#) - c#

I have a hash table which can contain any number of objects. All of these objects implement some similar methods / properties and some of their own.
For example all objects in the hashtable may have a method called PrintText taking a single parameter of type string. All the objects are however instantiated from different classes.
Is it possible for me to pull out a particular object from the hashtable by its key without knowing its type before runtime, and access all its own methods and properties (not just the common ones)?
Normally I would do something like,
MyClass TheObject = MyHashTable[Key];
But the object being pulled out could be derived from any class so I cannot do that in this instance.

You could define an interface containing the common methods and properties, and implement this interface in all your classes. Then you can easily access these methods and properties.
But to access the specific methods of an object (not contained in the interface), you will need to know the type of the object.
Update:
It's not clear from your question, but when you write about a hashtable, I assume you mean the Hashtable class. In that case, you should have a look at the generic Dictionary class (available since .NET 2.0). This class will make your code typesafe and saves you from a lot of type-casting, e.g:
IMyInterface a = new MyObject();
// with Hashtable
Hashtable ht = new Hashtable();
ht.Add("key", a);
IMyInterface b = (IMyInterface)ht["key"];
// with Dictionary
var dic = new Dictionary<string, IMyInterface>();
dic.Add("key", a);
// no cast required, value objects are of type IMyInterface :
IMyInterface c = dic["key"];

To solve problems with common methods and properties you can solve by making your classes to implement the same interface. However, I don't see how you can access non-common members. You can try to use Reflection.

dynamic in C# 4. Reflection in earlier versions.
EDIT: In some cases, defining a common interface can be both an efficient and clear way of achieving something of the nature you describe. ('inspired' by the accepted answer and/or others mentioning it - can't remember the timeline)

You can say:
object theObject = MyHashTable[Key];
Then you can say:
theObject.GetType()
.GetMethod("PrintText")
.Invoke(theObject, new object[] {"paramvalue"});

Related

What is the use of this class<T>

The following code I saw in one of StackOverflow sites. But it is not explained in detail and I am unable to understand. Would anyone explain this?
public class MyArray<T>
{
T[] array = new T[10];
public T GetItem(int index)
{
return array[index];
}
}
I would like to know if this is a class.
How to instantiate this class?
How can I use the T array in the class?
Whether the array need to be created outside or inside in the class?
Generic classes <T> have type parameters. Separate classes, each with a different field type in them, can be replaced with a single generic class. The generic class introduces a type parameter. This becomes part of the class definition itself. It allows you to define type-safe data structures, without committing to actual data types. The most common use of generics is to create collection classes. This results in a significant performance boost and higher quality code, because you get to reuse data processing algorithms without duplicating type-specific code.
The letter T denotes a type that is only known based on the calling location. The program can act upon the instance of T like it is a real type, but it is not.
I would like to know if this is a class.
Yes it is a class
How to instantiate this class?
MyArray<int> = new MyArray<int>();
or
MyArray<string> = new MyArray<string>();
Or anyother type you like
How can I use the T array in the class?
Since we know that one of the common use of generics is to create collection classes. So you can also use it that way.
Whether the array need to be created outside or inside in the class?
Question is little vague bcoz which class you are talking about the declaring class or the implementation class. But assuming that you are talking about the class where you implement or create the object of Class. It should be inside the class like normal object initiator.
1: Yes, it's a class; hence the use of the class keyword.
2: var myArray = new MyArray<Something>(); where Something could be any type (with maybe the odd exception).
3: From within the class, just refer to array. You won't be able to do a lot with the items themselves, though, since you don't know what type they are.
4: The code you posted creates the array inside the class. The array is hidden, and the only access to it is through the GetItem method. What you posted must be incomplete, though, since that would not be useful and would not work. You need to be able to do more than try to get an item.
I would like to know if this is a class.
Yes this is a class and are called as Generic Classes, A Generic
classes encapsulate operations that are not specific to a particular
data type. The most common use for generic classes is with collections
like linked lists, hash tables, stacks, queues, trees, and so on.
Operations such as adding and removing items from the collection are
performed in basically the same way regardless of the type of data
being stored.
How to instantiate this class?
MyArray<int> myArrayInstance= new MyArray<int>();
How can I use the T array in the class?
You can use the name of the variable array to use them inside the class. and use the reference to access it from outside the class.
Whether the array need to be created outside or inside in the class
You can populate the array inside the class or it can be populated from the MyArray Constructor. like the following:
public MyArray(T[] inputArrayElements)
{
array = inputArrayElements;
}
Additional note, How to use GetItem
You can use myArrayInstance, the instance of the class to call the method. the calling will be like the following:
int itemAtIndexs = myArrayInstance.GetItem<int>(5);
// which will give you the item # 5th index
This is a generic class. This means that <T> will be a type when it's instantiated. For example, based on your code example, you would instantiate it as:
MyArray<int> integerArray = new MyArray<int>();
This would instantiate a strongly typed array of integers. It does this by passing T throughout the class. The same class could be used to store strings by doing the following.
MyArray<string> stringArray = new MyArray<string>();
The reason for this is to allow container classes to be more flexible in terms of what types they can contain. This makes them more reusable. Before generics, if you wanted a dynamic list, you needed to use an ArrayList which cast everything to type Object and then required you to manually upcast it back to the type it was meant to be.
There are plenty of built in generic classes such as List<T>, Dictionary<TKey, TValue>, etc. They can be found in the System.Generics module.
I am preferring to post an answer based on what others guided me with the hope that it will be helpful people like me who are in the lower rung of C# and learning something new.
namespace GenericArray
{
public class MyArray<T>
{
T[] array = new T[5];
public MyArray(int size)
{ //Not used in this programme, because the no. of elements is already set above.
}
public void SetItem(int index, T value)
{
array[0] = value;
}
public T GetItem(int index)
{
return array[index];
}
}
}
In the button event, I code like this.
private void button4_Click(object sender, EventArgs e)
{
MyArray<int> myInt = new MyArray<int>(5); //Initializing the generic class.
myInt.SetItem(0, 1); //array element 0 is going to be assigned a value of 1.
MessageBox.Show(myInt.GetItem(0).ToString());
//You can also use the same class, to set string values.
}

Find the type of derived object. Defining Dictionary with mixture of object types

Here's what I have.
Class Parent
Class Child1
Class Child2
Both Child1 and Child2 derive from Parent. Parent is not abstract and classes are NOT static.
I have two questions:
1) I want to be able to load Dictionary with a mixture of Parent, Child1 and Child2 objects. What would be the syntax?
2) Later at runtime I would like to call a specific function of an object at a specific Dictionary index. How would I know the type of object and access that function?
To declare a dictionary that will operate across those types you would declare a dictionary to operate with the base type (Parent)[This works the same way with many collection types in .NET such as List, etc]. An example:
var myDictionary = new Dictionary<string, Parent>();
myDictionary.Add("1", new Child1);
myDictionary.Add("2", new Child2);
Later on you could iterate this dictionary, pull a key value pair out, and check the type of the object and do something specific with it.
foreach(var kvp in myDictionary){
var currentObject = kvp.Value;
if(currentObject.GetType() == typeof(Child1)){
var currentAsChild1 = currentObject as Child1;
//Do something special with this object a child1.
//I would put this block into its own method probably.
}
}
Dictionaries don't have what you would call an "index", and are instead key based. You could attempt to get the value of a specific key in the dictionary and perform similar logic to the logic displayed in the loop construct above.
Parent test;
if(myDictionary.TryGetValue("1", test){
//Perform similar type checking logic here, cast the object to the derived type and perform the specific logic on that specific type.
}
A big consideration you need to make though is do you really need to do this. One suggestion I have is that you consider using an interface or an abstract class so you don't need to do this in the first place. Another question to ask yourself is are these derived types really derived types? Do they fit under the "is a" moniker for creating a derived type? If you can extract a common contract of methods to call I would either create an abstract method in the base class or implement an interface so you're not having to write logic like this, as it is very brittle (resistant to change).
Some basic overview bits on dictionaries can be found here with more examples on using them: dotnetpearls

List, SortedList, Dictionary to store objects by key and serialize them?

My requirements:
I need to store a collection of objects inside a class,
objects must be accessible by their key (which will be unique string), search/remove/replace must work like this
MyClass somethingNew = new MyClass();
// set someproperties on somethingNew
somethingNew.Id = "FooBar";
// theOtherObject already contains an object with the key "FooBar"
theOtherObject.Members[somethingNew.Id] = somethingNew;
when new object is inserted no sort should happen,
the property (collection) must be serializable to XML using DataContractSerializer.
So, what to choose for Members property?
I guess that List and SortedList are out of the question, so I am about to use generic
Dictionary<string, MyClass>.
Is this the right decision? Does it support serialization?
Another class you may want to consider KeyedCollection<TKey,TItem>. It is also serializable.
The KeyedCollection class is a hybrid between a collection based on the IList generic interface and a collection based on the IDictionary generic interface. Like collections based on the IList generic interface, KeyedCollection is an indexed list of items. Like collections based on the IDictionary generic interface, KeyedCollection has a key associated with each element. *
*Referenced from MSDN documentation from link above.
Edit:
One thing to note is that KeyedCollection<TKey,TItem> is an abstract class and you will need to derive an instance of that class, ex) MyClassCollection before you can begin using it.
Dictionary<string, MyClass> is the correct option in this case.
And yes, it is Serializable.

Why Create a Class Derived from a Generic List (.NET)?

Whats is the difference between:
List<MyType> myList;
and
myList : List<MyType>
Its obvious that the first one is list and second one is a class. But my question is what's the advantage of second over first one.
The latter gives you the ability to have a function which takes a myList, instead of just a List. This also means that if the type of myList changes (perhaps to a sorted list) you don't have to change your code anywhere. So instead of declaring List<myType> everwhere, and then having to change them, if you had MyList objects everywhere, you're golden.
Its also a syntactic difference. Does myList have a list, or is it a list?
I would lean towards having a MyList : List<MyType> if it is used commonly throughout your program.
List<MyType> myList is an instance of the generic type List that can contain items that are of MyType (or of any types derived from MyType)
var myTypeInstance = new MyType();
var myList = new List<MyType>;
myList.Add(myTypeInstance);
myList : List<MyType> is a new type that inherits from List from which you can then make multiple instances:
var myTypeInstance = new MyType();
var myCollectionVariable = new myList();
myCollectionVariable.Add(myTypeInstance);
The main advantage of the latter over the former is if you wanted to have some methods that act on a List you can put them on your class, rather than storing them in a "helper" or "utility" library, for example:
class myList : List<MyType>
{
public void DoSomethingToAllMyTypesInList()
{
...
...
}
}
Object composition link text
vs.
Class inheritance link text
The latter is a new class that inherits from the base, but is distinct. The most obvious distinction is that it doesn't have the same constructors, but you'll also run into problems streaming it.
Those are the disadvantages. The advantage is that you could add some of your own methods. Even then, I'd consider using containment, with has-a relationship instead of is-a.
I would prefer not to inherit implementation where possible. It has its uses, but if it's not entirely necessary, then it's not worth it.
The major answer to your question is that by inheriting List<T>, you make all its methods public by default. Usually when writing a new class, you want encapsulation. You don't want to let the internals leak out. For example, suppose you wanted to make a thread-safe container. If you inherit from a thread-ignorant container, your clients will be able to use the public interface of the base class to bypass any locking you try to put in.
Another popular mistake comes when you find yourself using a particular container type a lot, it's tempting to try and use inheritance to make a short name for it:
class ShortName : Dictionary<string, List<string>> { };
But that's not what you've done - you've created a completely new type. This means that if you have some other library that can produce the right data structure, it won't be directly usable by your code; you'll have to copy it into a ShortName first. An example is Linq, which can easily build a Dictionary<string, List<string>> from a very readable, functional expression, ending with ToDictionary.
So instead, do this:
using ShortName = Dictionary<string, List<string>>;
Now you have a short snappy alias for the unweildy typename, but you're actually still using the same type.
The Microsoft design guidelines (FxCop and VS Code Analysis) don't recommend inheriting publicly-visible classes from List<T>. Instead you can inherit from Collection<T> as described in this blog post.
These guidelines aren't necessarily relevant for private assemblies or internal classes though.
A couple of reasons why you might want to inherit from Collection<T> or List<T> are:
So you can add custom application-specific members to your collection class.
So you can create a ComVisible collection class (you can't expose a generic List directly to COM, but you can expose a derived class).
By the way the naming guidelines would also recommend you name your derived class with the "Collection" suffix, i.e.
MyTypeCollection : List<MyType> // or : Collection<MyType>, IList<MyType>
rather than
MyList : List<MyType> // or : Collection<MyType>, IList<MyType>
Some people find benefits in abstracting data structures away from their application logic. If you decide that generic list is no longer the best data structure to represent MyList you can change your MyList implementation, and as long as your interface is the same, you don't have to update any other code.
This is over kill in many situations however.
There are also semantic benefits to working with an abstracted data type rather than the original, though the list type blurs the line. It is more obvious when working with a dictionary data structure. If you wrap the dictionary in a custom collection type, and expose keys and values as properties. you can write code that reads more like the business logic you are implementing.

Why can I not return a List<Foo> if asked for a List<IFoo>? [duplicate]

This question already has answers here:
In C#, why can't a List<string> object be stored in a List<object> variable
(14 answers)
Closed 8 years ago.
I understand that, if S is a child class of T, then a List<S> is not a child of List<T>. Fine. But interfaces have a different paradigm: if Foo implements IFoo, then why is a List<Foo> not (an example of) a List<IFoo>?
As there can be no actual class IFoo, does this mean that I would always have to cast each element of the list when exposing a List<IFoo>? Or is this simply bad design and I have to define my own collection class ListOfIFoos to be able to work with them? Neither seem reasonable to me...
What would be the best way of exposing such a list, given that I am trying to program to interfaces? I am currently tending towards actually storing my List<Foo> internally as a List<IFoo>.
Your List<Foo> is not a subclass if List<IFoo> because you cannot store an MyOwnFoo object in it, which also happens to be an IFoo implementation. (Liskov substitution principle)
The idea of storing a List<IFoo> instead of a dedicated List<Foo> is OK. If you need casting the list's contents to it's implementation type, this probably means your interface is not appropriate.
Here's an example of why you can't do it:
// Suppose we could do this...
public List<IDisposable> GetDisposables()
{
return new List<MemoryStream>();
}
// Then we could do this
List<IDisposable> disposables = GetDisposables();
disposables.Add(new Form());
At that point a list which was created to hold MemoryStreams now has a Form in it. Bad!
So basically, this restriction is present to maintain type safety. In C# 4 and .NET 4.0 there will be limited support for this (it's called variance) but it still won't support this particular scenario, for exactly the reasons given above.
In your returning function, you have to make the list a list of interfaces, and when you create the object, make it as an object that implements it. Like this:
function List<IFoo> getList()
{
List<IFoo> r = new List<IFoo>();
for(int i=0;i<100;i++)
r.Add(new Foo(i+15));
return r;
}
MASSIVE EDIT
You'll be able to do it with C# 4.0, but [thanks Jon]
You can get around it using ConvertAll:
public List<IFoo> IFoos()
{
var x = new List<Foo>(); //Foo implements IFoo
/* .. */
return x.ConvertAll<IFoo>(f => f); //thanks Marc
}
The simple answer is that List<Foo> is a different type to List<IFoo>, in the same way that DateTime is different to IPAddress, for example.
However, the fact that you have IFoo implies that collections of IFoo are expected to contain at least two implementations of IFoo (FooA, FooB, etc...) because if you expect there to only ever be one implementation of IFoo, Foo, then the IFoo type is redundant.
So, if there is only ever going to be one derived type of an interface, forget the interface and save on the overhead. If there are two or more derived types of an interface then always use the interface type in collections/generic parameters.
If you find yourself writing thunking code then there's probably a design flaw somewhere.
If, at the time that IList<T> was invented, Microsft had been aware that future versions of .net would support interface covariance and contravariance, it would have been possible and useful to split the interface into IReadableList<out T>, IAppendable<in T>, and IList<T> which would inherit both of the above. Doing so would have imposed a small amount of additional work on vb.net implementers (they would have to define both read-only and read-write versions of the indexed property, since for some reason .net doesn't allow a read-write property to do serve as a read-only property) but would mean that methods which simply need to read items from a list could receive an IReadableList<T> in covariant fashion, and methods which simply need a collection they can append to could receive an IAppendable<T> in contravariant fashion.
Unfortunately, the only way such a thing could be implemented today would be if Microsoft provided a means for new interfaces be substitutable for older ones, with implementations of the old interfaces automatically using default methods supplied by the new ones. I would think such a feature (interface substitutability) would be extremely helpful, but I wouldn't hold my breath waiting for Microsoft to implement it.
Given that there's no way to back-fit IReadableList<T> into IList<T>, an alternative approach would be to define one's own list-related interface. The one difficulty with doing so is that all instances of System.Collections.Generic.List<T> would have to be replaced with some other type, though the difficulty of doing that could be minimized if one were to define a List<T> struct in a different namespace which contained a single System.Collections.Generic.List<T> field and defined widening conversions to and from the system type (using a struct rather than a class would mean that code would avoid the need to create new heap objects when casting in any scenario where the struct wouldn't have to be boxed).

Categories

Resources