C# objects in arrayLists - c#

I'm working with ArrayList in C# and I am wondering how I can add objects to an ArrayList and then retrieve the values from it?
In short, how can I add, delete, edit and read from an ArrayList containing objects of classes?
Thankful for all help!

Unless you are in a situation where you must use .NET 1.0/1.1, or need to interact with legacy code that uses ArrayList - you should really avoid using ArrayLists in new code. Use the generic collection type List<> instead.
The operations to add, remove, and replace an item in List<T> are quite straightforward.
Let's say you have some hypothetical type Animal, instances of which you will store in a list:
Animal dog = new Animal("dog");
Animal cat = new Animal("cat");
List<Animal> animalList = new List<Animal>();
// example of adding items to the list
animalList.Add( dog );
animalList.Add( cat );
// example of removing items form the list
animalList.Remove( cat );
// example of replacing an item at a given position
animalList[0] = new Animal("giraffe");
The public interfaces for List<T> and ArrayList are actually quite similar. The main difference, is that ArrayList can only store object references since it was implemented before .NET supported generics.
ArrayList listOfObjects = new ArrayList();
int myAge = 207;
listOfObjects.Add( (object)myAge );
In the example above, you MUST cast types like int (which are value types in .NET) to object. This results in a boxing conversion - which copies the int value type to a new location on the heap, and passes it to ArrayList. Boxing conversions, are one of the disadvantages of using ArrayList - List<T> avoids this by virtue of being a generic class. Another issue is that ArrayList does not prevent you from mixing different types in the list together. For instance:
listOfObjects.Add( (object)myAge );
listOfObjects.Add( "Hello World" );
are both allowed. However, when accessing elements of an ArrayList, you must know what type you are trying to retrieve. This makes ArrayList more fragile as a collection type, because the caller must write code to either protect themselves from arbitrary types being stored in the ArrayList, or else use reflection and runtime type checks to convert the values being stored. List<T> avoids both of these problems by allowing the compiler to help verify that only appropriate types are stored in the collection (those that match the type parameter T in List<T>).
There's a great deal more that could be written about interacting with collections - and in fact there is. Here's a link to just one of many great books on the subject. My advice would be, before you begin writing code in .NET/C#, you should take the time to familiarize yourself with the basic concepts of the C# language and type system - what are reference vs. value types. What are primitives. What are generics. etc. This will help ensure that when you start writing code, the code does what you need it to do. C# has a sophisticated and rich type system- as well as a vast library of framework classes. It's important to have a good grounding in the core aspects of the language before you get too deep into writing actual code. Examples like those I show above will only get you so far - and they already introduce numerous language concepts: variables, constructors, generics, boxing conversions, etc.

Firstly, it is better to use a List, and not an ArrayList in C#. For instance, if you want a list of strings:
List<String> myList = new List<String>();
or
var myList = new List<String>();
Then the methods will be similar, e.g.
myList.Add("bla");
var test = myList[0];

you can do it the same as if u work on a list or a collection (do try use .add method).
also, you can read this msdn link

im using similar method but im not able to use it..giving some error like object is field cannot use as type..:/ im wondering I was able to use it in java even with a ArrayList object..im understating it bcz mine object is field but why I cannot use it:(
List lists = new List();
person p2 = new person("Hammad", "Lahore", 1, 123);
person p3 = new person("adnan", "Lahore", 1, 123);
person p4 = new person("qamar", "Lahore", 1, 123);
lists.Add(p2);

Related

Converting object (List<string>) to List<object>

Im trying to write a small framework for REST-API testing. Im using a lot of reflection and came to a problem I cant help myself.
Im using this line to extract a variable the user gives my as a path (string)
object o = input.GetType().GetProperty(name).propertyInfo.GetValue(input, null);
This object can be a normal type T or a List<T>.
Now if its a List and I know the type everything is simple, I can use
List<string> l = (List<string>)o; // I know its a List<string> because the user told me
To parse the object into the given array. But I dont always know the type of the objects in the list and
List<object> l = (List<object>)o; // I dont know the type and I dont care
gives me an error.
Object of type "System.Collection.GenericList[System.String]" can not
be converted to "System.Collection.GenericList[System.Object]"
Is there anything I can do to receive the list of objects? I dont want the user to specify the type because its only the last variable I want to care about. Like
The user wants to test "object1.a.b.c" I only need to know the type of c, because thats where the test runs.
TIA
You may convert it to IEnumerable<object>, but not List<object>. The reason is: a list of bananas is not a list of fruit because you can put an apple into a list of fruit, but not into a list of bananas. Since the two types allow different operations, they are not compatible.
A sequence has no "put into" operation, so it is possible to use a list of bananas as a sequence of fruit. Similarly, you can use a list of strings as a sequence of objects, but not a list of objects.
This feature is called generic covariance; for more information, do a search on C# covariance and you'll find plenty of articles explaining how it works.
Note in particular that covariance only works on reference types; you may not use a sequence of integers as a sequence of objects. Do you see why?
Alternatively, if you have an IEnumerable in hand, you can make a copy of any sequence into a list of objects with mysequence.Cast<object>().ToList(). But this is a copy, not a reference conversion.
Since your problem begins at processing dynamic objects that arrive as JSON to the server, it's quite convenient to use the JSON Processing library itself to test for certain characteristics before converting to POCOs. Using newtonsoft's JSON.Net,
var o = JObject.Parse(json);
JToken property = o["a"]["b"]["c"];
if (property != null)
{
if (property.Type == JTokenType.Array)
{
// Process property as array
}
else if (property.Type == JTokenType.Object)
{
// Process property as object
}
// Magnitude of other types
}
I do understand the need to convert to .NET types before final processing but I would highly recommend beginning with JObjects as the library is designed for this purpose and provides numerous convenience methods for many dynamic operations that C# doesn't provide natively.
JToken Type Reference
JObject Class

Converting List<object> to List<complex> where complex is a user-defined type

So lets say I have a class like
public class Complex { } // this is what I mean when I say List<Complex>
// its just a user-defined class or type if you will
Now let's say I have a method which returns a list that holds objects.
Now let's say I can further guarantee that each of these objects in the list is actually of type Complex (in other words List < Complex >)
I would like the most painless way of casting this list as possible. A one-liner would be ideal, but a few lines would be fine too.
Here is what I tried (but doesn't work - InvalidCastOperation exception):
// Sorry this is so hard to read! Also .Cast<Complex>() doesn't work either :(
return (ComplexCollection) ((List<Complex>) ((List<object>) complexElementsDictionary["ComplexElementCollection"]).OfType<Complex>());
Some specifics about this code snippet:
ComplexCollection inherits List<Complex>
complexElementsDictionary is of type (Dictionary<string, List<object>)
So in plain terms I'm asking a Dictionary<> for its corresponding list of objects. Then I try to cast this list to what its supposed to be, which is a list of Complex.
Note - Please try to ignore the fact that I am casting like this at runtime. I'm deserializing an XML collection (in app.config actually) and this is how I've chosen to do it. There may be a better way, but for now I just want to see if anyone knows a way to do what I'm asking.
Thank you so much! I hope it is clear what I'm asking, and if not I'll update the question.
Breaking up your example code and modifying it slightly to use Cast():
List<object> list = complexElementsDictionary["ComplexElementCollection"];
List<Complex> typedList = list.Cast<Complex>().ToList();
You now have a list of objects of the required type. But what you actually want is an instance of your collection object, and this cannot be obtained by another cast. That is, you can't do this:
ComplexCollection collection = (ComplexCollection)typedList;
because typedList simply isn't an instance of ComplexCollection and there is no conversion operator available to the compiler to convert from List<Complex> to ComplexCollection.
You will need to create your instance and add the Complex objects to it:
ComplexCollection collection = new ComplexCollection();
foreach(Complex c in typedList){
collection.Add(c);
}
Or in just four lines:
ComplexCollection collection = new ComplexCollection();
foreach(Complex c in complexElementsDictionary["ComplexElementCollection"].Cast<>(Complex)){
collection.Add(c);
}
To convert a List<object> to List<Complex> is as simple as:
List<object> objectList = complexElementsDictionary["ComplexElementCollection"];
List<Complex> complexList = objectList.Cast<Complex>().ToList();
However you can't cast a List<Complex> to ComplexCollection just because ComplexCollection inherits from List<Complex>. (the other way around is fine though)
List<T> has a constructor which takes an IEnumerable<T> and adds the elements to a list. So I think what you need is to add this constructor to ComplexCollection:
public ComplexCollection(IEnumerable<Complex> values) : base(values)
{
/* plus any other logic you have */
}
And then your example with the return statement becomes:
return new ComplexCollection(
complexElementsDictionary["ComplexElementCollection"].Cast<Complex>()
);
To convert a list to a new type you can just do something as simple as
(ComplexCollection)(yourList.Select(x => (complexType)x).ToList());
That should work, basically your going through your list of objects in the dictionary and casting each item to the appropriate type, then converting that to a list and then converting your list to the more specific collection type.
I'm afried there's no direct solution. Maybe you could use ConvertAll:
// ol is of type List<Object>
List<Complex> cl = ol.ConvertAll(o=>(Complex)c);

Why can't I cast from a List<MyClass> to List<object>?

I have a List of objects, which are of my type QuoteHeader and I want to pass this list as a list of objects to a method which is able to accept a List<object>.
My line of code reads...
Tools.MyMethod((List<object>)MyListOfQuoteHeaders);
But I get the following error at design time...
Cannot convert type 'System.Collections.Generic.List<MyNameSpace.QuoteHeader>'
to 'System.Collections.Generic.List<object>'
Do I need to do anything to my class to allow this? I thought that all classes inherit from object so I can't understand why this wouldn't work?
The reason this is not legal is because it is not safe. Suppose it were legal:
List<Giraffe> giraffes = new List<Giraffe>();
List<Animal> animals = giraffes; // this is not legal; suppose it were.
animals.Add(new Tiger()); // it is always legal to put a tiger in a list of animals
But "animals" is actually a list of giraffes; you can't put a tiger in a list of giraffes.
In C# this is, unfortunately, legal with arrays of reference type:
Giraffe[] giraffes = new Giraffe[10];
Animal[] animals = giraffes; // legal! But dangerous because...
animals[0] = new Tiger(); // ...this fails at runtime!
In C# 4 this is legal on IEnumerable but not IList:
List<Giraffe> giraffes = new List<Giraffe>();
IEnumerable<Animal> animals = giraffes; // Legal in C# 4
foreach(Animal animal in animals) { } // Every giraffe is an animal, so this is safe
It is safe because IEnumerable<T> does not expose any method that takes in a T.
To solve your problem you can:
Create a new list of objects out of the old list.
Make the method take an object[] rather than a List<object>, and use unsafe array covariance.
Make the method generic, so it takes a List<T>
Make the method take IEnumerable
Make the method take IEnumerable<object> and use C# 4.
You can't cast List<OneType> to List<OtherType> as it is actually the instances of the list you want to cast, as well as the List itself.
there is an extension method which will allow you to do this (MSDN reference):
IEnumerable<Object> myNewEnumerable = myEnumerable.Cast<Object>();
This method will attempt to cast each instance of the list of one type to the other type and add them to a new enumerable. it will throw an exception if any instance can't be cast.
As far as the system is concerned the two types for your lists are just different types, so it is like saying:
A objectOfTypeA;
B objectOfTypeB = (B) objectofTypeA;
To be able to do the cast there would have to be an implicit or explicit conversion between the types available, which there isn't (unless you provided one, which you might be able to do).
you expect it to work because List<object> will always be able to hold any type in another list, but when you think about it in those terms you can see why it doesn't.
I'm sure there is a more technically competent answer, but that is the gist of it I think.
you might be interested in reading Eric Lippert's series on Covariance and Contravariance as this may be helpful to you.
This question may also be useful
List<MyClass> x = someList.Select(f => (MyClass)f).ToList();
I'm presuming that you mean that the lists are of types which inherit from each other or can otherwise be cast from one type to another - in that case, try this:
Tools.MyMethod(MyListOfQuoteHeaders.Cast<OtherType>());
Thanks for the many responses.
I'll explain what I wanted to do and what I've come up with as a solution.
I needed a method that I could call by passing in a List of objects of any type and then output that list to XML. Also passed to the method would be a string which would be a system file structure path location which points to the location the XML file would be saved to. As I have an ever growing number of classes and types, I wanted to avoid writing multiple methods to cater for each type of class. I'm not sure if I've even gone about this the right way, but it's a lightweight solution to my problem and works. If there are any issues with it, or if anyone has any comments please feel free...
So... my method now looks like this...
public static Enums.Status WriteListToXML<T>(string outputPath, List<T> inboundList)
{
try
{
XmlSerializer xmlSerializer = new XmlSerializer(inboundList.GetType());
using (StreamWriter streamWriter = System.IO.File.CreateText(outputPath))
{
xmlSerializer.Serialize(streamWriter, inboundList);
}
return Enums.Status.Success;
}
catch (Exception ex)
{
return Enums.Status.Failure;
}
}
... and my calling line reads...
WriteListToXML<QuoteHeader>(#"C:\XMLDocuments\output\QuoteHeaders.xml", quoteHeadersList);
Like I said, it may not be the tidiest solution, but it works well in my scenario.
The problem is that at Compile time, the compiler emits 2 separate classes, 1 that represents List<MyClass> and one that represents List<Object>. They are essentially 2 separate types. That's how Generic types work, in .Net at least.
Assuming this is .Net, you could do
MyListOfQuoteHeaders.Cast<Object>()
which basically does
var objects = new List<Object>();
foreach(var item in MyListOfQuoteHeaders)
{
objects.Add((object)item);
}
return objects;

Selecting objects contained in an ArrayList

I'm working on a project for homework where I have an ArrayList containing 5 strings. I know how to select items of the ArrayList (using an index value) but not how to access the objects strings. Any help would be great. Here is what I've tried to do:
private ArrayList myComponents;
private int listIndex = 0;
myComponents = new ArrayList(); //Arraylist to hold catalog data
equipment = new Equipment(itemName, itemType, itemDetails, itemMaintenance, itemId);
myComponents.Add(equipment);
// class file is called Equipment.cs
// I know normally that equipment without the arraylist this would work:
// equipment.getitemName();
// but combining with the arraylist is being problematic.
You will likely be better off using a List instead of an ArrayList. An ArrayList is not strongly typed which means that you cannot treat the things/objects inside the array like they are "Equipment" but rather only like they are a generic boring object.
List<Equipment> myComponents = new List<Equipment> ();
equipment = new Equipment(itemName, itemType, itemDetails, itemMaintenance, itemId);
myComponents.Add(equipment);
foreach(Equipment eq in myComponents)
{
eq.getItemName();
// do stuff here
}
Let me know if this solves your problem.
An ArrayList doesn't know (or care) what kind of objects are placed in it. It treats everything put into it as an Object. When retrieving objects from the ArrayList you will need to convert the returned Object reference into a reference of the appropriate type before you can access that types properties and methods. There are several ways of doing this:
// this will throw an exception if myComponents[0] is not an instance of Equipement
Equipment eq = (Equipment) myComponents[0];
// this is a test you can to to check the type
if(myComponents[i] is Equipment){
// unlike the cast above, this will not throw and exception, it will set eq to
// null if myComponents[0] is not an instance of Equipement
Equipment eq = myComponents[0] as Equipment;
}
// foreach will do the cast for you like the first example, but since it is a cast
// it will throw an exception if the type is wrong.
foreach(Equipment eq in myComponents){
...
}
That being said, if possible, you really want to be using a generic type. The one that works most like an ArrayList is List. Generics help in a lot of cases to avoid all the casting that makes the ArrayList code painful to write and error prone. The downside is of course that you cannot mix types in a List. A List won't let you put a string in it, while an ArrayList full of Equipment instances will. The particular problem you are trying to solve will determine which makes more sense.
Since all the items in the array list are "objects" on the face of it, but they're actually Equipment objects under the covers, you need a way of going from object to Equipment when retrieving the items from the ArrayList (hint: Cast). Don't want to give it away since this is homework, but that should help....

What is the "< >" syntax within C#

I have been learning about the basics of C# but haven't come across a good explanation of what this is:
var l = new List<string>();
I don't know what the <string> is doing or if it's the List that is doing the magic. I have also seen objects been thrown within the < > tags.
Can someone explain this to me with examples, please?
That is the generic syntax for C#.
The basic concept is that it allows you to use a Type placeholder and substitute the actual real type in at compile time.
For example, the old way:
ArrayList foos = new Arraylist();
foos.Add("Test");
worked by making ArrayList store a list of System.Objects (The base type for all things .NET).
So, when adding or retrieving an object from the list, The CLR would have to cast it to object, basically what really happens is this:
foos.Add("Test" as System.Object);
string s = foos[1] as String.
This causes a performance penalty from the casting, and its also unsafe because I can do this:
ArrayList listOfStrings = new ArrayList();
listOfStrings.Add(1);
listOfStrings.Add("Test");
This will compile just fine, even though I put an integer in listOfStrings.
Generics changed all of this, now using Generics I can declare what Type my collection expects:
List<int> listOfIntegers = new List<int>();
List<String> listOfStrings = new List<String>();
listOfIntegers.add(1);
// Compile time error.
listOfIntegers.add("test");
This provides compile-time type safety, as well as avoids expensive casting operations.
The way you leverage this is pretty simple, though there are some advanced edge cases. The basic concept is to make your class type agnostic by using a type placeholder, for example, if I wanted to create a generic "Add Two Things" class.
public class Adder<T>
{
public T AddTwoThings(T t1, T t2)
{
return t1 + t2;
}
}
Adder<String> stringAdder = new Adder<String>();
Console.Writeline(stringAdder.AddTwoThings("Test,"123"));
Adder<int> intAdder = new Adder<int>();
Console.Writeline(intAdder.AddTwoThings(2,2));
For a much more detailed explanation of generics, I can't recommend enough the book CLR via C#.
It's generics - it's a form of type parameterisation. In your example, it's making l refer to a list of strings - the list will only ever contain strings: the compiler treats it (pretty much) as if everywhere that the API docs mention "T" it actually says "string". So, you can only add strings to it, and if you use the indexer you don't need to cast to string, etc.
To be honest, giving generics detailed coverage on an online forum is pretty much impossible. (In C# in Depth, I take nearly 50 pages talking about generics.) However, armed with the name of the feature, you should be in a much better position to find out more. The MSDN "Introduction to C# Generics" is probably a good starting point.
Asking specific questions about generics on SO is likely to yield good results - I just don't think it can really be covered properly in one question/answer.
This is .NET Generics. The type within the < > denotes the type of element contained in the list.
with ArrayList you'd have to cast the elements inside...
int x = (int)myArrayList[4];
with List you can avoid that step because the compiler already knows the type.
int x = myList[4];
Generics are available in .NET 2.0 and later.
Those are generics. You are making a List that only contains strings. You could also say
List<int>
and get a list that only contains ints.
Generics is a huge topic, too big for a single answer here.
Those are known as Generics (specifically List is a generic class).
Reading from MSDN
Generics (C# Programming Guide)
An Introduction to C# Generics
Generics in the .NET Framework
This is generics in action. A regular List stores items of type Object. This requires casting between types. This also will allow you to store any kind of item in one instance of a list. When you are iterating through items in that list you cannot be sure that they are all of a certain type (at least not without casting each item). For instance lets say you create a list like this:
List listOfStrings = new List();
Nothing prevents someone from doing something like this:
listOfStrings.add(6); //Not a string
A generic list would allow you to specify a strongly-typed list.
List<string> listOfStrings = new List<string>();
listOfStrings.add("my name"); //OK
listofStrings.add(6); //Throws a compiler error
There is a more thorough examples on here Generics
< > is for generics. In your specific example, it means that the List is a List of strings, not say a list of ints.
Generics are used to allow a type to be, well, generic. It's used ALOT in Collections to allow them to take different types so that they can function much like a normal array and still catch invalid types being assigned at compile time. Basically it allows a class to say "I need to be associated with some specific type T, but I don't want to hard code exactly what that type is, and let the user select it.". A simple array for instance might look something like:
public class MyArray<T> {
private T[] _list;
public MyArray() : this.MyArray(10);
public MyArray(int capacity)
{ _list = new T[capacity]; }
T this[int index] {
get { return _list[index]; }
set { _list[index] = value; }
}
}
Here, we have a private list of type T that is accessed by using our class like a normal array. We don't care what type it is, it doesn't matter to our code. But anyone using the class could use it as, say MyArray<string> to create a list of strings, while someone else might use it as MyArray<bool> and create a list of flags.

Categories

Resources