What would be the best way to make a System.Collections.Generic.List that should only be accessed by an enum? To help describe what I'm looking for, this how I'm doing it right now:
enum MyEnum
{
First,
Second,
Count
}
class MyClass
{
List<SomeClass> myList = new List<SomeClass>((int)MyEnum.Count);
MyClass()
{
myList[(int)MyEnum.First] = new SomeClass(1);
myList[(int)MyEnum.Second] = new SomeClass(2);
}
}
I feel like I'm missing something. Is there a better way of doing this? I'm sorry if the answer is obvious, I found it very difficult to search for something that sounded so generic.
As some background, I would be using this list to access different textures in my code, e.g. the enum would have texture names and each texture would be placed in and later accessed from the List using that texture name.
Would it be possible to use Dictionary instead of List?
var myDict = new Dictionary<MyEnum, SomeClass>();
...
myDict[MyEnum.First] = new SomeClass(1);
myDict[MyEnum.Second] = new SomeClass(2);
Or, as #JimHurley suggested (see http://msdn.microsoft.com/en-us/library/bb531208.aspx) just
var myDict = new Dictionary<MyEnum, SomeClass>()
{
{ MyEnum.First, new SomeClass(1)},
{ MyEnum.Second, new SomeClass(2)}
};
If you want to add a new element to List<T> you have to use it's Add method.Indexer can be used only to modify existing items. I think in this case using a Dictionary<MyEnum, SomeClass> would be more appropriate.
Related
I have a dictionary that contains another dictionary as value
something like this
Dictionary<string, Dictionary<double,double>>
now I want to sort it by internal dictionary's value
how can I do that??
From the looks of your comment
sorry i am not expert on c#, would you suggest a way to store 3 values as one item?
I would suggest creating a class and sort on it like this
public class MyClass
{
public string StringProperty {get;set;}
public int FirstDoubleProperty {get;set;}
public int SecondDoubleProperty {get;set;}
}
Then create a collection like this
List<MyClass> MyClasscol = new List<MyClass>();
MyClass mc = new MyClass();
mc.StringProperty = "User1225072";
mc.FirstDoubleProperty = 5;
mc.SecondDoubleProperty = 6;
MyClasscol.Add(mc);
mc = new MyClass();
// and So on
then sort like this
var newsortedcollection = MyClasscol.OrderBy(x => x.FirstDoubleProperty);
Assuming you are now trying to figure out how to store and order a collection of objects with multiple properties, then you have a few options. Nikhil Agrawal's answer is a great solution but there are times when you may not need/want to create a custom class for this. For these situations (preferably when your code is private and not part of some API) then the alternatives below might be an option.
KeyValuePairs
Based on your requirements and your original post using dictionaries, it seems like instead of a dictionary of dictionaries (multi-tiered), you probably wanted a dictionary of keyvaluepairs (flat).
// using keyvaluepair
var keyValueDict = new Dictionary<string, KeyValuePair<double, double>>();
keyValueDict.Add("string", new KeyValuePair<double, double>(5.8, 7.4));
var sortedKeyValues = keyValueDict.OrderBy(x => x.Value.Key);
Tuples
An alternative to the not so pleasant KeyValuePair is the Tuple introduced in .NET 4. The tuple is a generic class which allows you to store typed property values without creating your own custom class. It is worth noting that there are tuple implementations for up to 8 properties.
// using tuple
var tupleList = new List<Tuple<string, double, double>>();
tupleList.Add(new Tuple<string, double, double>("string", 5.8, 7.4));
var sortedTuples = tupleList.OrderBy(x => x.Item2);
There are some good SO questions about Tuples if you are interested:
Is Using .NET 4.0 Tuples in my C# Code a Poor Design Decision?
Are EventArg classes needed now that we have generics
I can't seem to figure out why the following doesn't work.
From reading around it seems it must be somehow related to something like this.
public class Test<T>
{
public void SomeFunction(IList<IList<T>> ListOfLists)
{
}
}
....
List<List<SimpleClass>> lists = new List<List<SimpleClass>>();
new Test<SimpleClass>().SomeFunction( (IList<IList<SimpleClass>>)lists );
How can I require a list to actually be a list of lists? I can't seem to grasp what I am doing wrong.
Thanks,
A List<List<SimpleClass>> isn't an IList<IList<SimpleClass>>.
For example, for the latter type, you could call lists.Add(new SimpleClass[5]) as SimpleClass[] implements IList<SimpleClass>. But you can't do that with a List<List<SimpleClass>>, because each element has to be a List<SimpleClass>.
This would be okay though:
List<IList<SimpleClass>> lists = new List<IList<SimpleClass>>();
Can I define an array such that the first element is String, the Second is an int and the third is a textbox?
It's like when we create a List we choose type of element List<string >
Update from Comment:
Sorry I couldnt explain.I need to like
this List<string,int,object> Firstly i
will set type and when i call the list
i will not need to cast
thanks
create list of objects. in C# everything is derived from object
List<object> list = new List<object> {"first", 10, new TextBox()};
EDIT(To comment):
Then you should create seperate class to hold those three items , or use Tuple
List<Tuple<string,int,TextBox>> list;
You can declare an array of object and do that. You're talking about a mixed type array, right?
var arr = new object[] { "Hi", 42, 3.7, 'A' }
If you need an array that has elements without a common base-class other than object, then you're going to need an array of objects!
object[] myArray = new object[] { "Hi", 23, new TextBox() };
Note that this is not really something you should doing. If you need to associate disparate types like this, a class makes much more sense.
You want a Tuple<string,int,TextBox>, not an array.
IMHO the best way to do this is through a List<> of objects:
String s = "hey!";
int i = 156;
TextBox t = new TextBox();
List<object> list = new List<object>(3);
list.Add(s);
list.Add(i);
list.Add(t);
The reason this works is because (almost?) everything in C# derives from the base-class object
Arrays are typically homogeneous collections, which means that every object contains in the array is of the same type (or at least shares a common parent type). An array of [string, int, textbox] could be defined as an object[] but that's really misuse of arrays.
Just create a proper class which contains the 3 fields.
class MyType {
public string myString;
public int myInt;
public Listbox myListbox;
}
If you're looking make a list of string, int, textbox, you can either create a class which has those members or look at the Tuple class in .net 4.0
List<Tuple<string,int,TextBox>
Define a class that contains the 3 types then define an array that contains the new type.
Object[] myObjects = new Object(){"myString", 42, textbox1};
System.Collections.Generic.Dictionary<string, object> source = new System.Collections.Generic.Dictionary<string, object>();
source.Add("A", "Hi");
source.Add("B", 10);
source.Add("C", new TextBox());
While accessing
string str = Convert.ToString(source["A"]);
int id = Convert.ToInt16(source["B"]);
TextBox t = (TextBox)source["C"];
I will suggest that you create a Type such as
enum ItemType { Int, String, Textbox }
class MyType {
public object objValue;
public ItemType itemType;
}
List<MyType> list = new List<MyType>();
.......
You can iterate through the list or extract the list by type such as below.
var intList = list.Where(e=>e.itemType == ItemType.Int);
Of course you can achieve the above with the enum and using the reflected Type info directly from the object, but I just think it is clearer this way also more explicitly list out the type your list can hold rather than just all type in the CLR
I am trying to achieve the following without LINQ:
I have a list of CenterDetail objects (with CenterID and AreaID as property):
objCenterDetail1 (CenterID=1, AreaID=1)
objCenterDetail2 (CenterID=2, AreaID=1)
objCenterDetail3 (CenterID=3, AreaID=1)
objCenterDetail4 (CenterID=5, AreaID=2)
objCenterDetail5 (CenterID=6, AreaID=2)
I want to create an AreasDictionary as follows:
AreaID=1: objCenterDetail1, objCenterDetail2, objCenterDetail3
AreaID=2: objCenterDetail4, objCenterDetail5
What is the best solution for this in C# with .NET 2.0?
You probably want something like this:
Dictionary<int, List<CenterDetail>> map = new Dictionary<int, List<CenterDetail>>();
foreach (CenterDetail detail in details)
{
List<CenterDetail> list;
if (!map.TryGetValue(detail.AreaID, out list)
{
list = new List<CenterDetail>();
map.Add(detail.AreaID, list);
}
list.Add(detail);
}
return map;
Not using LINQ typically means using foreach to iterate over your collection instead:
IEnumerable<Center> centers = // Assume this is your collection;
Dictionary<Area,List<Center>> areasDictionary = new Dictionary<Area,List<Center>>();
foreach(Center center in centers)
{
if (!areasDictionary.ContainsKey(center.Area) )
areasDictionary.Add(center.Area, new List<Center>());
areasDictionary[center.Area].Add(center);
}
Now this probably won't compile in your solution since you haven't given us enough information about the particular types involved, but it does demonstrate the general idea.
This question already has answers here:
A generic list of anonymous class
(22 answers)
Closed 8 years ago.
Is there any way to declare a list object of anonymous type. I mean
List<var> someVariable = new List<var>();
someVariable.Add(
new{Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}}
);
This is because I need to create a collection at runtime.
How about dynamic?
List<dynamic> dynamicList = new List<dynamic>();
dynamicList.Add(new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } });
It involves a bit of hackery but it can be done.
static List<T> CreateListFromSingle<T>(T value) {
var list = new List<T>();
list.Add(value);
return list;
}
var list = CreateListFromSingle(
new{Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}}
);
You can make a list like this, but you'll again have to use some serious hackery, and you'll have to use some "type by example" situations. For example:
// create the first list by using a specific "template" type.
var list = new [] { new { Name="", Phones=new[] { "" } } }.ToList();
// clear the list. The first element was just an example.
list.Clear();
// start adding "actual" values.
list.Add(new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } });
In general you can use the (arguably bad-smelling) cast by example trick others have mentioned to create instances of any generic type parameterized with an anonymous type for the type argument. However, for List<T> there is a slightly less gross way to do it:
var array = new[] {
new {
Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}
}
};
var list = array.ToList();
Your sketch of a proposed syntax is similar to a feature we did not implement for C# 3 or 4, but we considered. We call the feature "mumble types", and it would go something like this:
List<?> myList = new List<?>() {
new {
Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}
}
};
We call it "mumble types" because of course you'd read it "myList is a new list of hrmmf". :-)
The idea is that the compiler would look at the initializers and do its best to figure out what the type could possibly be, just the same way as how "var" means "look at the initializer and figure out what the type of the variable is". Whether we'd use "var" as the "mumble" or "?" (which is similar to what Java does in a related feature), or something else is an open question.
In any event, I wouldn't hold my breath waiting for this feature if I were you. It hasn't made the cut for several language versions so far, but it will stay on the list of possibilities for a while longer I think. If, hypothetically speaking, we were to be designing future versions of the language. Which we might or might not be. Remember, Eric's musings about future versions of C# are for entertainment purposes only.
Here's an approach that is somewhat cleaner than many of the other suggestions:
var list = Enumerable.Repeat(new { Name = "", Phones = new[] { "" } }, 0)
.ToList();
// ...
list.Add(new { Name = "Krishna",
Phones = new[] { "555-555-5555", "666-666-6666" } });
You can't make a collection of an anonymous type like this.
If you need to do this, you'll need to either use List<object>, or make a custom class or struct for your type.
Edit:
I'll rephrase this:
Although, technically, it's possible to make a list of an anonymous type, I would strongly recommend never doing this. There is pretty much always a better approach, as doing this is just making code that is nearly unmaintainable. I highly recommend making a custom type to hold your values instead of using anonymous types.
A custom type will have all of the same capabilities (since anonymous types are defined, by the compiler, at compile time), but will be much more understandable by the developer who follows you...
And just to play, too, here's my entry for "code I'd never actually want to use in the real world":
var customer = new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } };
var someVariable = new[]{1}.Select(i => customer).ToList();
I spent quite a lot of time trying to find a way to save myself some time using a list of anonymous types, then realised it was probably quicker just to use a private class inside the current class...
private class Lookup {
public int Index;
public string DocType;
public string Text;
}
private void MyMethod() {
List<Lookup> all_lookups = new List<Lookup> {
new Lookup() {Index=4, DocType="SuperView", Text="SuperView XML File"},
new Lookup() {Index=2, DocType="Word", Text="Microsoft Word Document"}
};
// Use my all_lookups variable here...
}
I don't think this is possible. Maybe in C# 4 using the dynamic keyword?