if class type list is there named
Collection<PurchaseOrderDetail> poDetails = new Collection<PurchaseOrderDetail>();
and another list with same type is there named _poH.PODetail
why _poH.PODetail = poDetails.ToList(); generates an error
Cannot implicitly convert type 'System.Collections.Generic.List'
to 'System.Collections.ObjectModel.Collection'
what is the solution for this, any explanation please.
All the reason behind the question is
_poH.PODetail = poDetails;
made poDetails.RemoveAt(Convert.ToInt32(e.RowIndex)); updates as well so I was searching for some thing like _poH.PODetail = poDetails.ToCollection();
According to the error message, _poH.PODetail is of type Collection, so assigning a list to it doesn’t work. But since poDetails is a collection itself, you can just assign it directly:
poH.PODetail = poDetails;
So you don’t actually need to call ToList() on it to convert it to a list.
There is no ToCollection method you could call on enumerables, but you could use the Collection constructor that takes a list to make it wrap that list and create a readonly collection:
new Collection(poDetails.ToList());
The short answer is simply that the ToList<T> extension returns an instance of List<T> class which, although similar, is not the same type as Collection<T>.
Basically this doesn't work for the same reasons you cannot set a string value to an integer variable.
One thing you can do though, is initializing the content of a new collection instance with an IList<T> instance. Therefore, the following should give you exactly what you want:
_poH.PODetail = new Collection(poDetails.ToList());
Also, as poke suggested, you might also want to assign the PODetail property with the poDetails variable itself.
_poH.PODetail = poDetails;
However, you must remember that Collection<T> is a reference type. This means that the objects in your collection won't be "copied" inside _poH.PODetail; instead, both poDetails and _poH.PODetail will be pointing to the exact same collection. Any changes done to one collection will automatically be reflected on the other.
Related
I have a list collection of following type
CoordinateCollection pointCoordinates = new CoordinateCollection();
it adds up list of type vector.
I want to remove duplicate entries from the list
I am trying like this
pointCoordinates = pointCoordinates.Distinct();
it gives me an error
cannot implicitly convert type 'system.collections.generic.ienumerable<SharpKML.Base.Vector> to SharpKML.Dom.CoordinateCollection
Please help me in solving this. I want unique set of records
Since CoordinateCollection implements ICollection<Vector> and Vector overrides Equals + GethashCode you can use Distinct. But you need to use the constructor of CoordinateCollection to create a new:
pointCoordinates = new CoordinateCollection(pointCoordinates.Distinct());
Note that i'm not familiar with SharpKML, i have looked at it's source code.
As the message states, you can't implicitly assign an object of type system.collections.generic.ienumerable<SharpKML.Base.Vector> to an object of type SharpKML.Dom.CoordinateCollection. I would suggest using one of their type conversion methods (documented here).
Distinct is going to return an IEnumerable<SharpKML.Base.Vector>. You can't assign that type to your CoordinateCollection instance because even though is is an IEnumerable<SharpKML.Base.Vector> it may not also be an instance of CoordinateCollection.
If you need an instance of CoordinateCollection create/use a constructor that will take an IEnumerable<SharpKML.Base.Vector> as input otherwise if an IEnumerable<SharpKML.Base.Vector> will do then declare your variable as such.
Given a generic list of type List<T> how do I find type T?
I suppose if the list is populated I could take listInstance[0].GetType() but that seems a bit hackish.
Edit:
For context, I want to populate a DataTable with columns based on the Properties of an object. Where an object property is a generic list I want to add a column for each property of the object stored by the list. I'll flatten the data structure to fit into a DataRow later.
The reason I don't want to use the type of the first object in the list is because it's not guaranteed that every instance will have the list populated. Some will and some won't, but I'll still need all the columns ahead of time.
You could try
typeof(List<T>).GetGenericArguments()[0]
This works with an empty array, while your version does not.
UPDATE:
On an instance use
instance.GetType().GetGenericArguments()[0]
Why is that hackish?, is not hackish at all. That is why the GetType() method exits. To obtain the type of the object.
You can use
myList.GetType().GetGenericArguments()
This returns an array of all the types specified in the declaration of the object.
It is hackish because if the list isn't populated, you can't get an answer.
You'll need to reflect against the Type:
List<int> mylist = new List<int>();
Type listType = mylist.GetType();
Type genericType = listType.GetGenericArguments()[0];
Do it as you said. It is not hackish.
You can also call GetType() directly on your list and use it to look at type of its its T.
You could also do listInstance[0] is SomeTypeIExpectThisToBe if you are expecting a type and want to do something because of that
You should have access to the type parameter, so you can use typeof:
void ProcessList<T>( List<T> listInstance)
{
Type type = typeof(T);
}
I'm trying to set up a class so that it's possible to initialize it using an object initializer, but it contains some collections. Ideally I'd like client code to be able to do:
MyClass myObj = new MyClass
{
Name = "Name",
Contents = new[]
{
"Item1",
"Item2"
}
}
However, where Contents needs to be a BindingList<string>. The underlying field stores a readonly reference to this list, and I'd like the setter to essentially do a Clear followed by AddRange to set the contents.
I can't make the Contents property an IEnumerable<string>, because client code wouldn't see the Add method, among many others, at least not without casting it first. I can't make it a BindingList<string> because if I set it, I need to construct a new binding list to pass to it.. this might be possible but I'd rather not introduce the inefficiency of construct a new BindingList<string> solely for the purpose of passing it to the property setter.
The ideal thing to be able to do would be to have the getter return a BindingList<string> and the setter accept IEnumerable<string>, but C# doesn't allow getters/setters on a property to have different types.
Oh, and implicitly casting between BindingList<string> and IEnumerable<string> is a no-no, so I can't do that either (http://blogs.msdn.com/b/peterhal/archive/2005/06/20/430929.aspx).
Is there any way around this?
C# initializer syntax will automatically call the Add method on your property's collection object. That won't call Reset() beforehand of course, but the object is still empty at that point, so it doesn't matter.
Does replacing the list have to use property set syntax? Having a setter replace the content of a collection without actually changing the collection object identity is very unexpected and will likely lead to bugs.
Create a custom collection class that derives from BindingList<string> and add an implicit cast from type string[]
I would recommed encapsulating the BindingList. In this situation go back to the old school way of creating objects so that you aren't creating unnecessary couplings. Favor good OO over language conventions.
I would like to get the Type of item that a BindingSource is hooked up to or configured for. The BindingSource.DataSource property can be set to an object, list, or type. If it is a Type, it obviously does not have a bound item yet, but I would still like to get the Type. For a List, I need the item Type, not the list type.
I currently have a custom list type for business objects that implement an IListItemType interface, that I created to solve this problem a while back. I would now like to get this working in a more generic fashion so that it will work with any list.
I've looked through the API docs for for a good way to do this, but so far I have not had any luck. Am I missing something or is this just something I can not or should not be doing?
I recently ran across the ListBindingHelper class in the framework that has everything I was looking for:
System.Windows.Forms.ListBindingHelper.GetListItemType()
Returns the type of an item contained in a list or collection.
ListBindingHelper.GetListItemProperties()
Returns a PropertyDescriptorCollection that describes the properties of the items contained in the list.
There is no completely generic way to get the "type" of the list. The most common method is to examine the first item, but this can be misleading as you can have objects that are of a more specific type in a collection that is less specific (in other words, the collection might be a List<object>, but the first item might be a string, leading you to guess that it's a List<string>). If you're confident that all of the elements will be the same type (meaning none are more specific than the generic type of the collection or than any of the other objects), then examining the first item is the easiest.
Apart from that, you could examine the list's actual type using GetType and check its interfaces. Chances are that any collection that's strongly typed is going to implement IEnumerable<T>, so you can iterate over its interfaces looking for IEnumerable that's generic, then look at its generic type arguments. It's (more than) a little hokey, but it should work.
TL;DR Version
Try this. Assuming you're using .NET 3.5 and have the list stored in a variable called list:
var listType = list.GetType().GetInterfaces()
.Where(t => t.Name == "IEnumerable" && t.IsGenericType)
.Select(t => t.GetGenericArguments()[0]).FirstOrDefault();
As long as the list implements IEnumerable<T>, this will give you T. If it doesn't, chances are the list type is object anyway.
It's been quite a while since this answer has been on board but just in case anybody is still looking for the answer...
I ran into a similar problem. My scenario was that BindingSource.DataSource would always be bound to an IEnumerable BUT there may not be any items in the list. It turns out that BindingSource has a private instance member called "itemType". This field does just what you're looking for: it shows the element type of a list if the BindingSource is bound to a list, or it shows the type of the object that the BindingSource is bound to, if there is no list.
To access the field value, I used some hacky reflection:
FieldInfo fi =
typeof(BindingSource)
.GetField("itemType", BindingFlags.NonPublic | BindingFlags.Instance);
Type myElementType = fi.GetValue(DataBinder.RestrictedDataBinding) as Type;
Without doing much research, I kind of assume that what it's doing is showing the element type of the innerList, which is why it doesn't matter if the DataSource is a list type or not. Also, I assume this field would accurately show the element type of any kind of list that is supported by the BindingSource (including IQueryables, etc.).
WARNING: I have NOT tested this field much so I don't know if there are cases that would make it not read the correct element type. For example, does the field always get accurately updated when the BindingSource's DataSource property is reset? What if the DataSource property is reset to a list that has a different elementType? In my case, these exceptions and others don't apply but you might want to test them.
Lastly, using reflection to hack into private fields breaks all kinds of oop principles. Keep that in mind. Also, keep in mind that there very well might be a good reason why the itemType field was hidden. If you need to investigate further, the code for the BindingSource class is publicly available.
I am trying to call a class method dynamically depending on a condition. This is how I am doing it
I have three classes implement a single interface
interface IReadFile
{
string DoStuff();
}
The three classes A,B,C implement the interface above.
I am trying to add them to a hashtable with the code below
_HashT.Add("a", new classA());
_HashT.Add("b", new classB());
_HashT.Add("c", new classC());
This compiles fine, but gives a runtime error.{Object reference not set to an instance of an object.}
I was planning to return the correct class to the interface type depending on a parameter that matches the key value. say if I send in a. ClassA is returned to the interface type and the method is called.
IReadFile Obj = (IReadFile )_HashT["a"].GetType();
obj.DoStuff();
How do I correct the part above where the objects need to be added to the hashtable? Or do I need to use a different approach? All the classes are in the same assembly and namespace.
Thanks for your time.
As a guess, you have not instantiated your _HashT object.
You need somewhere in your code (declaration or constructor probably) to instantiate it:
HashTable _HashT = new HashTable();
If you do not do this, _HashT will be null and an attempt to add to it will fail with a NullReferenceException as you have been getting.
It appears you are seeing a NullReferenceException. Based on the limited code you provided I would say it is likely that the _HashT variable is not assigned. It could be possible that the exception is being generated from one of your class constructors as well.
If you use Dictionary<> you can use the following code to add and extract objects from the hashtable.
var hashtable = new Dictionary<IReadFile>();
hashtable.Add("a", new ClassA());
hashtable.Add("b", new ClassB());
hashtable.Add("c", new ClassC());
IReadFile obj = hashtable["a"];
obj.DoStuff();
Following your approach, you do not need to call GetType() on the value you pull out of _HashT. The value should already be an object of type IReadFile.
Why are you calling GetType? The IReadFile object is the thing you are putting in the hash. Casting a Type object into a IReadFile is not going to cast correctly.