Something similar to C# .NET Generic List in java - c#

How would be a c# .net generic list in java?
somthing like that:
public class ClientList : List<Client> { }
the answer from Nikil was perfect, I just want to add to whoever wants to create a class from the List:
public class ClientList extends ArrayList<Client>

Java's List interface (java.util.List) can be generified. In other words, instances of List can be given a type, so only instances of that type can be inserted and read from that List. Here is an example:
List<String> list = new ArrayList<String>();
This list is now targeted at only String instances, meaning only String instances can be put into this list. If you try to put something else into this List, the compiler will complain.
The generic type checks only exists at compile time. At runtime it is possible to tweak your code so that a String List has other objects that String's inserted. This is a bad idea, though.
Accessing a Generic List
You can get and insert the elements of a generic List like this:
List<String> list = new ArrayList<String>();
String string1 = "a string";
list.add(string1);
String string2 = list.get(0);
Notice how it is not necessary to cast the object obtained from the List.get() method call, as is normally necessary. The compiler knows that this List can only contain String instances, so casts are not necessary.
Iterating a Generic List
You can iterate a generic List using an iterator, like this:
List<String> list = new ArrayList<String>();
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String aString = iterator.next();
}
Notice how it is not necessary to cast the object returned from the iterator.next() next call. Because the List is generified (has a type), the compiler knows that it contains String instances. Therefore it is not necessary to cast the objects obtained from it, even if it comes from its Iterator.
You can also use the new for-loop, like this:
List<String> list = new ArrayList<String>();
for(String aString : list) {
System.out.println(aString);
}
Notice how a String variable is declared inside the parantheses of the for-loop. For each iteration (each element in the List) this variable contains the current element (current String).

Related

Why doesn't the Lookup that results from GroupBy have Lookup properties?

I am trying to understand the System.Linq.Lookup class. When calling GetType(), the following displays:
System.Linq.Lookup`2+Grouping[System.Object,System.Data.DataRow]
What does the back tick mean?
What does the 2+ mean?
What is the Grouping class that follows the 2+?
Further, in the Fiddle's Inspect() method, why does lookup have a Key property rather than a Count and Item property?
The ultimate goal is to learn how to bind this to a nested ASP.NET repeater. We've already succeeded by casting the result to a Dictionary<string, DataTable>. We suspect, though, that it's possible to bind directory to the GroupedEnumerable once we understand its structure.
Fiddle
public static class Program
{
public static void Main()
{
var dt = GetData();
var enumerable = dt.AsEnumerable();
var grouped = enumerable.GroupBy(dr => dr["Name"]);
Inspect(grouped);
}
public static void Inspect(IEnumerable<IGrouping<object, DataRow>> grouped)
{
LogType("grouped", grouped);
var lookup = grouped.FirstOrDefault();
LogType("lookup", lookup);
LogType("key", lookup.Key);
var item = lookup.FirstOrDefault();
LogType("item", item);
}
public static void LogType(string label, object v)
{
Console.WriteLine("\n" + label.PadRight(10) + v.GetType());
}
public static DataTable GetData()
{
DataTable dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("StartDate");
dt.Columns.Add("EndDate");
for(var i = 0; i < 10; ++i)
{
var row = dt.NewRow();
row["Name"] = i % 2;
row["StartDate"] = DateTime.Now;
row["EndDate"] = DateTime.Now;
dt.Rows.Add(row);
}
return dt;
}
}
Output
grouped System.Linq.GroupedEnumerable`3[System.Data.DataRow,System.Object,System.Data.DataRow]
lookup System.Linq.Lookup`2+Grouping[System.Object,System.Data.DataRow]
key System.String
item System.Data.DataRow
Edit
Forked Fiddle that retrieves the values from the GroupedEnumerable.
Answers in my own words:
What does the back tick mean? The back tick indicates the number of type parameters that a class takes. In this case, it says that the Lookup class takes two type parameters.
What does the 2+ mean? The 2 belongs to the back tick not the the +. The plus means that we're accessing a class that's nested within another class. In this case, it means that we're accessing the Grouping class that's nested within a Lookup class.
What is the Grouping class that follows the 2+? It's a class nested within the Lookup.
Further, in the Fiddle's Inspect() method, why does lookup have a Key property rather than a Count and Item property? The lookup has a Key property because it isn't a Lookup; it's a Grouping that's nested inside a Lookup.
System.Linq.Lookup`2+Grouping[System.Object,System.Data.DataRow]
System.Linq.Lookup`2 is represented in C# as System.Linq.Lookup<T,U> (the back tick means the class is a generic and the number is the number of generic parameters).
The +Grouping means that there is a class defined inside of the System.Linq.Lookup`2 class called Grouping.
The two types inside the square brackets are the two types that the generic (System.Linq.Lookup) closes over.
So the full type, written in C# looks like this:
System.Linq.Lookup<object, System.Data.DataRow>.Grouping
The type doesn't need an Items property because it implements IEnumerable, which means the type itself can be iterated over (just like any other IEnumerable such as List<T>).
Not all lists/collections have a Count property, there is nothing that says they have to. You can get the count by calling the Count() extension method, but that could cause the entire enumerable to be iterated over, which may or may not have a significant performance cost.
This is CLR standard type syntax.
`2 means that the type has two generic parameters.
+ means a type that is nested inside another type.
In this case, it's telling you that the Grouping class is nested inside a Lookup class with two generic parameters.
As you can see from the source, the only public property that it defines is Key.

Can I initialize Dictionary Values automatically?

Let's say I want to store my data as a bunch of named lists.
I really like how with Dictionary, you can do:
myDictionary["SomeKey"] = new List<string>{ "SomeString" };
But unfortunately, I cannot safely do:
myDictionary["SomeKey"].Add("SomeString");
Because if the List at SomeKey has not yet been initialized, I'll get a null reference exception.
So everytime I alter a value in the dictionary, I have to do:
if (!myDictionary.ContainsKey("SomeKey")) myDictionary["SomeKey"] = new List<string>();
Before I can safely add to each list. It looks ugly and distracts from non-boilerplate code. I also duplicate code in several places (accessing SomeKey several times when all I want to say is "add this element to the list at SomeKey, regardless of whether it is empty or not").
There is basically no reason why I would want uninitialized values in my Dictionary. If it was an array of List, I would have looped through every element beforehand and initialized each member; I can't do this with Dictionary because I don't know what the keys will be in advance.
Is there a more concise syntax for saying, "access the value at this key, and if it is null, then initialize it"?
I don't think there is, but you could do it as an extension method if you wanted. Something like
public static class DictionaryExtensions
{
public static SafeAdd(this Dictionary<string,List<string>> obj, string key, string val)
{
// your example code
}
}
then you could do myDictionary.SafeAdd("somekey","somestring");

How to check if an object is a list enum type objects?

I have an object that can be a list of different enum types or non-enum types (normal class instances).
To verify if object is a list is easy:
myobject is IList
Now I can verify the type of list's elements:
(myobject as IList)[0].GetType().IsEnum
But how to verify if my list's elements are enums IF I have no elements yet ?
if (myobject is IList)
{
if ((myobject as IList).Count > 0)
{
if ((myobject as IList)[0].GetType().IsEnum)
return true;
}
else
{
// how to check if the list is enum list here ?
}
}
An IList can contain whatever type it wants, so if you don't have any contents you have no way of checking. If you actually have a generic type to start with you can check by using the GetGenericArguments method of Type. (GetInterface added in case you have something that's implementing IList but doesn't have the IList type as it's first generic argument).
myobject.GetType().GetInterface("System.Collections.Generic.IList").GetGenericArguments()[0].IsEnum
You can look at the the indexer's PropertyType via Type.GetProperty:
List<int> list = new List<int>(); // an empty List<T>
Type type = list.GetType().GetProperty("Item").PropertyType; // System.Int32
bool isEnum = type.IsEnum; // of course false
List<DayOfWeek> days = new List<DayOfWeek>();
type = days.GetType().GetProperty("Item").PropertyType;
isEnum = type.IsEnum; // true
demo: http://ideone.com/3JyEf
Having just IList you can't do that - IList does not gurantee types of objects inside of it and does not let you know type of objects it would accept.
Consider uisng generic veriosn IList<T> if possible - you'll be able to get type without elements in the list.
Unless your list is a generic list you cannot, since a non generic list may contain any object.
If list is generic then inspect generic type parameters for enum types.
If list is not generic try to resolve item type by inspecting parameters of Add, IndexOf or indexer methods. It is a very ugly way to do it, but may give you a clue since many old implementations inherits List object and adds an Add overload, or some new and lazy implementations may be used to hide generic parameters like public class MyObjectList: List<MyObject> {}.
The solution everyone is proposing:
IList<Days> list = new List<Days>();
if (list is IList<Days>)
{
Console.WriteLine("list has days");
}

If method returns interface type, why can't I pass the result to a concrete type?

The question maybe a little confusing, but it's hard to make clear this question in a subject title.
I have method declared and implemented like this:
public IList<string> GetBookTitles()
{
IList<string> bookTitles = new List<string>();
// do something to populate the bookTitles list.
return bookTitles;
}
Why can't I pass the result of this method to a List<string>? After all, List<string> is a kind of IList<string>.
Well, for starters, just look at the members of IList and compare it with List. List has methods that an IList doesn't. (List has a BinarySearch method that IList doesn't, just as a single example.)
Arrays also implement IList, as an example. An array however is not a List, so you can't, and shouldn't, be able to pass a string[] to a method that accepts a List<string>.
You have a few possible solutions. One would be to just change your method to return a List<string> rather than an IList<string> (that's what I'd suggest). If that's what you really need then you shouldn't be restricting the return type to IList<string>. Another (poorer) option would be to cast the result back to a List<string> before passing it to the next method, since you happen to know that it's what the underlying type really is.
After all, List<string> is a kind of IList<string>.
But there are also other kinds of IList<String>.
What if your method were to return an IList<String> which is a ReadOnlyCollection<String> instead?
IList<string> x = new ReadOnlyCollection<string>();
List<string> y = x; //Huh?
The compiler uses the signature of your methods, not the implementation when deciding if you can assign the result of GetBookTitles to your variable, so it can't know that the result will in fact be a List. If it would allow you to do such a thing, then you could write something like this:
List<string> myBooks = GetBookTitles();
myBooks.Sort();
In your example you could do this, and in fact you can if you cast the result of your method:
List<string> myBooks = (List<string>)GetBookTitles();
But then one day you could decide that your book collection is not modifiable, and you rewrite your method as follows:
public IList<string> GetBookTitles()
{
IList<string> tmp = new List<string>();
// do something to populate the bookTitles list.
IList<string> bookTitles = new ReadOnlyCollection<string>(tmp);
return bookTitles;
}
ReadOnlyCollection does not implement Sort, so your app would compile, but would crash at runtime.
Using the cast approach it would crash when trying to do the cast, but in this case you are taking the responsibility of deciding that that kind of cast is feasible and do not have the compiler trying to guess.
A better approach could be to use as instead of the cast and chek for null. I.e.:
List<string> myBooks = GetBookTitles() as List<string>;
if (myBooks != null)
myBooks.Sort();
You should be able to, you just need an explicit conversion.
List<string> foo = (List<string>)GetBookTitles()
should do it.
The interface may be implemented in various classes which are not same. So, it will be difficult to find the respective class.
You can type cast from IList to List!!!

C# .NET List declaration.Size unknown

I have to declare a list and use it in my code.How ever the number of elements that i will add to list will vary during each time I run my code.So how can I create a list and add elements to it dynamically with out specifying its size during declaration?
var myList = new List<string>();
myList.Add("foo");
myList.Add("blah");
// and on and on ...
List's in .Net will automatically resize themselves as you add to them.
You don't have to specify the bounds of a list (as you do with arrays). You can keep on calling Add() method to add elements in the list. You can create either a generic list which takes only specified types of objects and a non-generic list that only takes objects:
Generic:
List<int> intList = new List<int>();
intList.Add(10);
intList.Add(20);
Non-Generic:
ArrayList objList = new ArrayList();
objList.Add(New Employee());
objList.Add(20);
objList.Add("string");
The later can take any type of object but is not type-safe.
The System.Collection namespace is full of collection classes that can dynamically contract and expand its size, see the Generic namespace for the most used classes: http://msdn.microsoft.com/en-us/library/system.collections.generic.aspx
I recommend sticking with a List if you doubt what you are doing:
var list = new List<string>();
list.Add("test1");
list.Add("test2");
list.Remove("test1");

Categories

Resources