I have some code I always use to make collections of my object. This code and be used like 10 times in some of my project with the object replaced.
Is there any way I can create this as a function that can take whatever object? I've heard of <T> but I am unsure how to use it in this.
public class PageCollection : CollectionBase
{
public void Add(Page item)
{
InnerList.Add(item);
}
public void Remove(int index)
{
InnerList.RemoveAt(index);
}
public void Remove(Page item)
{
InnerList.Remove(item);
}
public Page this[int index]
{
get
{
return (Page)InnerList[index];
}
set
{
InnerList[index] = value;
}
}
}
Just use List<T> object to create strongly typed collection of your objects. In your example use just
List<Page> listOfPages = new List<Page>()
Also check System.Collections.Generic namespace for strongly typed (generic) collections.
Best go to the source:
http://msdn.microsoft.com/en-us/library/512aeb7t.aspx
Related
Recently, when handling collections of objects of the same (base-)class,
I´ve recently found myself writing something like this:
class SomeClass {
public bool PropertyA {get; set;}
}
class EncapsulatingClass {
private List<SomeClass> list = new();
private bool propA;
public bool PropertyA {
get { return propA; }
set {
propA = value;
foreach(SomeClass instance in list)
instance.PropertyA = value;
}
}
}
This is of course so I don´t have to use foreach every time I want to set a property for the collection. While this works fine, I feel like this requires a lot of code for something simple and a lot of repitition with each property.
Is there a better solution, like extracting the logic of "apply this for the property of the same name for each object in the list" into a function and just calling that in the setters?
There is the issue of ownership of the property. If you need to enforce synchronization such that setting PropertyA ins the encapsulating class, all the instances in the list also use the same value.
For example
class SomeClass
{
public SomeClass(EncapsulatingClass parent)
{
Parent=parent;
}
public EncapsulatingClass Parent { get; }
public bool PropertyA { get => Parent.PropertyA; }
}
class EncapsulatingClass
{
private List<SomeClass> list = new List<SomeClass>();
private bool propA;
public bool PropertyA
{
get { return propA; }
set
{
propA = value;
}
}
}
Otherwise, you have multiple PropertyA values, one for each instance, and then you have to decide which one is the master value, and what to do if some are different.
I'm wondering what it is you are doing to need this so often. It makes me think there's a flaw in the design of your application you could avoid by restructuring something but it's difficult to say without more information.
For your specific problem I would discard EncapsulatingClass and use the ForEach method on List<T> for a little more concise code:
myList.ForEach(s => s.PropertyA = true);
Alternatively, if you don't always use List<T> you can write your own extension method to work on all IEnumerables:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var t in source)
action(t);
}
// Call it just like previously:
myIEnumerable.ForEach(s => s.PropertyA = true);
Of course, this is still cumbersome if you need to do it a lot. But I suspect if you do, it's probably a flaw in the design.
I might approach this with a custom List class providing a single mass update method.
public class EasyUpdateList<T> : List<T>
{
public void UpdateAll(Action<T> update)
{
if (update == null)
return;
foreach (T item in this)
update(item);
}
}
Now you don't need a specific encapsulating class, you can just create a new EasyUpdateList and update any number of properties across the collection using the UpdateAll method.
EasyUpdateList<MyClass> list = new EasyUpdateList<MyClass>();
list.Add(instance1);
list.Add(instance2);
...
list.UpdateAll(x =>
{
x.Property1 = "Value1";
x.Property2 = "Value2";
});
This still uses a foreach loop but is much more generic and you don't have to change your other classes or write repeated code for each one.
Of course you could also achieve this with an extension method for a List class if you don't want a new class.
public static void UpdateAll<T>(this IList<T> list, Action<T> update)
{
if (update == null)
return;
foreach (T item in list)
update(item);
}
I'm trying to make an object to hold some strings. The object can be anything, including collections, arrays ... The strings need to be enumerable (IEnumerable or similar). Each string indexer needs to be known by intellisense and Reflection is a last option. One single object, no separate object for indexers.
Example usage:
public static class features
{
public const string favorite = "blue background";
public const string nice = "animation";
}
public static class Program
{
public static void Main()
{
foreach (string feature in features)
{
Console.WriteLine(feature);
}
//... select a feature
Console.WriteLine(features.favorite);
}
}
EDIT:
I will use the first solution proposed by Jim Mischel, modified to use reflection, as that gets the advantages I'm interested in at the current time.
encapsulates everything in one entity
names are directly associated with values
enumerator is dynamic
public IEnumerator<string> GetEnumerator()
{
FieldInfo[] strings = this.GetType().GetFields();
foreach (FieldInfo currentField in strings)
{
yield return currentField.GetValue(null).ToString();
}
yield break;
}
I thank everyone for your effort.
Offhand, I can think of two ways to do it. However, since it must be IEnumerable<string> it can't be a static class because static classes can't implement interfaces. Nor can static methods implement interface methods.
The first way uses constants and an enumerator that just returns them in order:
public class Features: IEnumerable<string>
{
public const string Favorite = "blue background";
public const string Nice = "animation";
public IEnumerator<string> GetEnumerator()
{
yield return Favorite;
yield return Nice;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
The second way stores the values in an array and uses an enum for the indexes. The enumerator just returns the enumerator for the array. Again, this is not static because of the enumerator, and also because indexers can't be static.
public enum FeaturesIndex
{
Favorite = 0,
Nice = 1
}
public class Features2 : IEnumerable<string>
{
private static readonly string[] _features = new string[]
{
"blue background",
"animation"
};
public string this [FeaturesIndex ix]
{
get { return _features[(int) ix]; }
}
public IEnumerator<string> GetEnumerator()
{
return ((IEnumerable<string>) _features).GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
A third possibility, as pointed out by others, is using a dictionary and either an enumeration or defined constants as keys. It's an interesting approach, the only potential drawback being that you can't guarantee the order in which keys will be returned when you enumerate the collection. If that's a problem, you could have your enumerator sort the sequence before returning.
Any way you look at it, there are tradeoffs. Both of my solutions require manual synchronization of keys and values. In the first, you have to make sure that the enumerator retures all of the values. In the second, you have to ensure that your enum matches the array.
Pick your poison.
It also depends on how you're going to use the thing. My first solution has the benefit of simplicity and would probably be quite acceptable if it's a write-once, use-forever kind of thing. The second option has the benefit of using an indexer, which is more commonly associated with collections.
There are many better ways to do this. To follow a similar pattern to what you're looking for, here's one way of doing it:
public static class features
{
public enum TYPES { favorite, nice }
public static Dictionary<TYPES,string> values = new Dictionary<TYPES,string>() {
{ TYPES.favorite, "blue background" },
{ TYPES.nice, "animation" } };
}
public static class Program
{
public static void Main()
{
foreach (string feature in features.values.keys)
{
Console.WriteLine(features.values[feature]);
}
//... select a feature
Console.WriteLine(features.values[TYPES.favorite]);
}
}
So really what you are asking for is an object with Properties you can change and is also enumerable, but makes it so you don't need to call reflection to enumerate unless absolutely necessary.
If what I assume you are actually looking is the following
public class Features: IEnumerable<string>
{
private readonly Dictionary<string,string> _internalCollection;
public Features()
{
_internalCollection = new Dictionary<string,string>();
}
private string GetByKey(string id)
{
if(!_internalCollection.ContainsKey(id))
return null;
return _internalCollection[id];
}
private void SetByKey(string id, string value)
{
_internalCollection[id]=value;
}
const string _favoriteId = "favorite";
public string Favorite
{
get { return GetByKey(_favoriteId); }
set { return SetByKey(_favoriteId,value);}
}
const string _niceId = "nice";
public string Nice
{
get { return GetByKey(_niceId);}
set { return SetByKey(_niceId, value);}
}
public string this[string index]
{
get { return GetByKey(index.ToLower()); }
set { return SetByKey(index.ToLower(), value);}
}
public IEnumerator<string> GetEnumerator()
{
foreach(var key in _internalCollection.Keys)
yield return _internalCollection[key];
yield break;
}
}
I have a problem with the generic class. I have something like this:
public abstract class IGroup<T> : IEnumerable where T : class {
protected List<T> groupMembers;
protected List<IGameAction> groupIGameActionList;
public IGroup() {
groupMembers = new List<T>();
groupIGameActionList = new List<IGameAction>();
//groupIGameActionList.Add(new DieGameAction(groupMembers));
}
}
And second class:
class DieGameAction : IGameAction {
List<object> gameObjectList;
public DieGameAction(List<object> objectList) {
gameObjectList = objectList;
}
}
I don't know how to cast or convert groupMembers in commented line. This doesn't work because it can not be converted (List<T> to List<object>). So how can I do it?
groupMembers.Cast<object>().ToList();
But that doesn't look a good thing to do. You are creating a new empty list that will not be related to the original anymore.
The way you're gonna be using these classes will tell if that would be a good idea.
If you're planning to have both lists updated by adding items to a single class, it will not fit. Then maybe your DieGameAction should be generic as well: DieGameAction<T>.
Then you could give the original list without casting.
But, there's another danger: if you set a new list to the IGroup, it will not be reflected to DieGameAction.
So, it all depends on what you're trying to do.
Old question but by declaring your variable as IList instead of List<object>, you can assign a list (or array) of any type to the variable and simply cast it to List<Whatever> later (of course it's going to throw an exception if you cast it to a wrong type). I have found this more efficient than having to do .Cast<object>() every time you want to assign something to the variable.
I'm going to focus only on providing a solution.
You can make DieGameAction use IList < object > instead:
class DieGameAction : IGameAction {
IList<object> gameObjectList;
public DieGameAction(IList<object> objectList) {
gameObjectList = objectList;
}
}
Then you can provide an IList < object > implementation which adapts any IList < T >.
public abstract class IGroup<T> : IEnumerable where T : class {
protected List<T> groupMembers;
protected List<IGameAction> groupIGameActionList;
public IGroup() {
groupMembers = new List<T>();
groupIGameActionList = new List<IGameAction>();
groupIGameActionList.Add(new DieGameAction(new ObjectListAdapter<T>(groupMembers)));
}
}
I'm going to try and provide one of the many possible solutions using as base the System.Collections.ObjectModel.Collection < T > which can also wrap an IList < T >:
public class ObjectListAdapter<T> : System.Collections.ObjectModel.Collection<T>, IList<object>
{
public ObjectListAdapter(IList<T> wrappedList)
: base(wrappedList)
{
}
public int IndexOf(object item)
{
return base.IndexOf((T)item);
}
public void Insert(int index, object item)
{
base.Insert(index, (T)item);
}
public new object this[int index]
{
get
{
return base[index];
}
set
{
base[index] = (T)value;
}
}
public void Add(object item)
{
base.Add((T)item);
}
public bool Contains(object item)
{
return base.Contains((T)item);
}
public void CopyTo(object[] array, int arrayIndex)
{
this.Cast<object>().ToArray().CopyTo(array, arrayIndex);
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(object item)
{
return base.Remove((T)item);
}
public new IEnumerator<object> GetEnumerator()
{
return this.Cast<object>().GetEnumerator();
}
}
The list changes will throw a type casting exception upon trying to use an unsupported object, the way I programmed it over here, but you can also handle that as you like.
Now, for IList < object > you could also try using IList instead which is also implemented by List < T > so you'll basically have to do nothing more to get this working.
Note that the important thing is that the list will appear the same at both places used since they will basically be using the same underlying List object.
Let me know if this answers your question, by marking it as an answer, or not to refrain :)
I just faced the same problem which led me here. The solution that worked for me was to cast into IEnumerable of Object instead of List of Object
(System.Collections.Generic.IEnumerable<object>)groupMembers;
I had similar issue today but i called the LINQ .ToArray() on it directly and it works fine. that should be shorter than casting.
so you could say
groupMembers.ToArray();
It worked for me like this:
List<myclass> listMyclass = new List<myclass>();
var listObject = listMyclass.ToList<object>();
I have class called GroupItem, i can store any type here say int, string, decimal, datetime etc.., Then, i have GroupItems which will store any groupItem. I'm using an arraylist to store all the groupItem.
public class GroupItem<T>
{
private string heading;
private List<T> items = new List<T>();
public GroupItem() { }
public string Heading
{
get { return heading; }
set { heading = value; }
}
public List<T> Items
{
get { return items; }
set { items = value; }
}
public void Add(T value)
{
this.items.Add(value);
}
public T this[int index]
{
get
{
return this.items[index];
}
}
}
public class GroupItems
{
private string groupName;
private List<object> items = new List<object>();
public string GroupName
{
get { return groupName; }
set { groupName = value; }
}
public GroupItems() { }
public void Add(object value)
{
this.items.Add(value);
}
public object this[int index]
{
get
{
return this.items[index];
}
}
}
I want to retrieve from GroupItems. How i can get generic item's values in groupItems?
I'm now inserting two items, datetime and int to groupitems. Now i want to retrieve groupitems[2] value but how i can convert this to groupItem without knowing what it is. Even we may get its genericarguments by getType().getGenericarguments()[0]. But how i can create an instance based upon that.
If the list is storing heterogeneous items, then I would suggest you need a common non-generic interface or base-class. So, say we have
interface IGroupItem {
// the non-generic members, and maybe
// "object Value {get;}" etc, and maybe
// "Type ItemTypr {get;}"
}
You would then have:
class GroupItem<T> : IGroupItem {...}
an you would then use
List<IGroupItem> ...
instead of ArrayList, or, franky, in place of GroupItems {...}
What I'd do is create a generic collection such as:
public class GroupItems<T> : List<GroupItem<T>>
{
}
If you need to extend the basic functionality of a list, you could also extend Collection<T> and override the methods you need:
public class GroupItems<T> : Collection<GroupItem<T>>
{
protected override void InsertItem(int index, T item)
{
// your custom code here
// ...
// and the actual insertion
base.InsertItem(index, item);
}
}
How about just replacing your GroupItems class with List<GroupItem<T>> ?
Depending on what you do with GroupItem you should either inherit from List/Collection as was offered by other or use a generic collection inside your class
e.g.
class GroupItem<T>
{
private List<T> items = new List<T>();
public void Add(T value)
{
items.Add(value);
}
public T Get()
{
//replace with some logic to detemine what to get
return items.First();
}
}
There are two situations that could be covered by your question:
You want to simply store a collection of GroupItem's of type T in the class GroupItems.
You want to store a collection of generic GroupItem's of any type in the class GroupItems. To better clarify, I mean that you could store GroupItem<DateTime> or GroupItem<int> in the same GroupItems class.
Here are some ways of going about storing and retrieving for both scenarios:
Same Type
public class GroupItem<T>
{
// ... Code for GroupItem<T>
}
public class GroupItems<T>
{
private List<GroupItem<T>> mItems = new List<GroupItem<T>>();
public void Add(T item)
{
mItems.Add(item);
}
public T GetItem(int index)
{
return mItems[index];
}
}
Here you will build a collections that contain GroupItem's of the same time, so a collection of GroupItem<DateTime> for example. All the items will be of the same type.
Generic Type
public interface IGroupItem
{
// ... Common GroupItem properties and methods
}
public class GroupItem<T>
{
// ... Code for GroupItem<T>
}
public class GroupItems
{
private List<IGroupItem> mItems = new List<IGroupItem>();
public void Add(IGroupItem item)
{
mItems.Add(item);
}
// This is a generic method to retrieve just any group item.
public IGroupItem GetItem(int index)
{
return mItems[index];
}
// This is a method that will get a group item at the specified index
// and then cast it to the specific group item type container.
public GroupItem<T> GetItem<T>(int index)
{
return (GroupItem<T>)mItems[index];
}
}
Here you will be able to build and maintain a single collection that can contain any GroupItem with any Type. So you could have a GroupItems collection that contains items of GroupItem<DateTime>, GroupItem<int>, etc.
Please note that none of these code examples take into account any erroneous circumstances.
Consider: you have a collection of items; the items may have any runtime type (string, int, etc.). Because of this, the static type of the collections items must be object.
It seems that you want to be able to retrieve items from the list with strong static typing. That's not possible without a lot of conditional logic (or reflection). For example:
object item = collection[0];
if (item is int)
//do something with an int
else if (item is string)
//do something with a string
Now suppose instead of "doing something" with the value of collection[0], we assign the value to a variable. We can do one of two things:
use the same variable for both cases, in which case the static type must be object.
use separate variables, in which case the static type will be string or int, but outside of the conditional logic, we can't know which variable holds the value of collection[0].
Neither option really solves the problem.
By creating GroupItem<T>, you add a level of indirection to this problem, but the underlying problem is still there. As an exercise, try reworking the example, but starting from "Consider: you have a collection of items; the items are of type GroupItem<T> where T may be any runtime type (string, int, etc.)."
Thanks for your inputs.
I have resolved it myself using multiple overloading methods to resolve this.
for example:
private void Print(GroupItem<string> items)
{
///custom coding
}
private void Print(GroupItem<int> items)
{
///custom coding
}
Though its not efficient enough, i want to do in this way as it was .net 2.0.
I'm now improving this in .Net 4.0 with new algorithm.
Thanks a lot for all of your helps.
In my CMS I have a load of modules which allow me to do some clever item listing stuff. I am trying to use them to pull out a list of their child objects via reflection, but am getting stuck with the level of generics involved.
I have got as far as this method:
var myList = moduleObj.GetType().GetMethod("ChildItems").Invoke(moduleObj, new object[] { });
which returns a List. Each modulespecificobject is bound it an IItemListable interface which has the methods in it I am trying to access.
I am unsure how I can cast or iterate the myList object as a set of IItemListable objects access the methods required.
Thanks
A few of the classes:
public interface IItemListable
{
IQueryable GetQueryableList();
string GetIDAsString();
IItemListable GetItemFromUrl(string url, List<IItemListable> additionalItems);
bool IsNewItem();
IItemListable CreateItem<T>(ItemListerControl<T> parentList) where T : class, IItemListable;
IItemListable LoadItem(string id);
IItemListable SaveItem();
RssToolkit.Rss.RssItem ToRssItem();
void DeleteItem();
string ItemUrl();
}
public interface IItemListModule<T> where T: IItemListable
{
List<T> ChildItems();
}
public class ArticlesModule : ItemListModuleBase<Article>, IItemListModule<Article>
{
#region IItemListModule<Article> Members
public new List<Article> ChildItems()
{
return base.ChildItems().Cast<Article>().Where(a => a.IsLive).ToList();
}
#endregion
}
You can direct cast while iterating:
IList myList = (IList)moduleObj.GetType().GetMethod(
"ChildItems").Invoke(moduleObj, new object[] { });
foreach (IItemListable o in myList)
{
}
Edit: I would better mark ChildItems as virtual in the base then you could write
public override List<Article> ChildItems()
{
return base.ChildItems().Where(a => a.IsLive).ToList();
}
and
var myList = moduleObj.ChildItems();
foreach (IItemListable o in myList)
{
}
without any need to cast, avoiding the use of the new keyword and without having to use reflection.
Maybe this will help:
http://devlicio.us/blogs/louhaskett/archive/2007/06/13/how-to-cast-between-list-t-s.aspx
(Also some extra links in the comments)