ICollection cast problem - c#

Is there any solution to solve the problem with this cast example? I need to add a new element to the collection, so I have to solve it.
IEnumerable enumerable;
IEnumerable enumerable2;
enumerable = new ObservableCollection<Something>();
enumerable2 = new ObservableCollection<Object>();
ICollection<Object> try = (ICollection<Object>)enumerable; //Don’t work
ICollection<Object> try2 = (ICollection<Object>)enumerable2; //Work

Check out covariance and contravariance with generic parameters in C# 4. It might provide you with more information for future when faced with such problems.

I'm not sure 100% that this is what you mean, but have you tried this:
IEnumerable<Object> try3 = enumerable.Cast<Object>();
Ok, it didn't work, how about dynamic typing:
dynamic var = new Something();
dynamic try1 = enumerable;
try1.Add(var);

If all you know is object, then the non-generic interfaces are your friend:
IList list = (IList)foo;
list.Add(yourItem);
However! Not all enumerable items are lists, so not all can be added in this way. IList underpins a lot of data-binding, so is a good bet.

"try" is a reserved word in C#. Have you tried another variable name? or you could use #try if you need to use the "try" variable name.

You can iterate through the something collection and insert the elements into the object one.

If you have control over the relevant code, it is perhaps time to rethink the design a little. One often tries to use the most restricted interface possible that can still achieve the desired result. It seems in this case that IEnumerable cannot achieve that result, if one of the things you want to do is to add new items. Changing to a more appropriate type might be a better solution than having to cast the collection.

Use the Cast extension combined with a ToList.
IEnumerable ie1 = new ObservableCollection<string>();
ICollection<object> ic1 = (ICollection<object>)ie1.Cast<object>().ToList();
Or iterate through manually.

Dynamic typing works (Only one bad thing, that I have to link windows.csharp and system.core dlls, which are ~1MB, so it's not the best for a silverlight app, but It's the best solution, which I know now.)

Related

Lazy<T> as Lazy<object> possible?

Is it possible to cast a Lazy<T> instance as a Lazy<object> when all I have is an object reference?
This returns null:
var result = obj as Lazy<object>;
That makes sense to me. It should be null because its not a Lazy<object>. But is there another way to interrogate to find out what T actually is or cast to object? I actually don't care what T actually is in this case. I just need the .Value reference.
Some background
So this is really a curiosity question. It could be applied to any object specifying a generic (i.e. List<T>). But here's the specific case:
I'm sticking a Lazy<T> provider in a cache. I know what T is when I put it in and I know what T is in the normal use when i pull it out.
However, in one case when I'm managing the cache, I don't know what T is and really I don't want to interact with it except to send its value to a serializer. I'm just concerned I'm missing some obvious way to achieve this without creating a way to track it ahead of time or change a bunch of method signatures/calls.
This is what the dynamic keyword is for. It uses the same reflection solution underneath as #SledgeHammer's answer, except that it has a cache for the getter delegates so it's a lot faster if you do it more than once for the same T. It's also a lot shorter and easier to read (and write).
object result = (obj as dynamic).Value;
The way you asked the question, you would need to use reflection (or expression trees) to do it:
Lazy<int> l = new Lazy<int>(() => 5);
object o = l;
object val = o.GetType().GetProperty("Value").GetGetMethod().Invoke(o, null);
Classes in C# cannot be covariant, so there is no way for you to treat that object instance as a Lazy<object>. You'll have to create a new Lazy object that simply uses the other Lazy to determine what the value should be. Doing so is simple enough:
Lazy<T> oldLazy = ComputeOldLazy();
Lazy<object> newLazy = new Lazy<object>(() => oldLazy.Value);

How to get first item from XmlSchema.Elements

I have XmlSchema object. Which has Elements property. I need a first element from it. I cant figure how to get it not writing foreach/break (which would look stupid). Is there a nice way?
EDIT: the only way I found is : getenumerator/movenext/value;
EDIT2: one of the ways is to cast XmlSchema.Elements.Values (ICollection) to a meaningful type to use with Linq. The problem is that I cant find that type. The GetType gives me name: "System.Xml.Schema.XmlSchemaObjectTable+ValuesCollection"
I dont see this type in the ObjectExplorer and I cant cast to it..
Please answer if you have working solution rather than just throwing in whatever comes to your head. Thanks.
Use linq on the Names or Values of the elements, depending on what you need
E.g.,
var v = yourObject.Elements.Names.OfType<XmlQualifiedName>().FirstOrDefault();
var w = yourObject.Elements.Values.OfType<XmlSchemaElement>().FirstOrDefault();
===
Edited: Added OfType<> to get an ICollection<> instead of an ICollection so that it is possible to use FirstOrDefault
Note: I verified this solution on the example XmlSchema from http://msdn.microsoft.com/en-us/library/system.xml.schema.xmlschema%28v=vs.110%29.aspx, if your element names or values have a different type you'll need to change that in the OfType<>

Polymorphic return type in c#

I have a function that currently prototyped as:
List<object> get_object_list(byte object_type, object_void_delegate get_one_specific_type_object)
{}
As the logic of getting a list of elements is the same for all the types I have, but the logic for getting one element , is different from one type to another , I was hoping to have one function for getting all sort of list ( get_object_list() ).
for example for type Car I would call:
List<Car> cars_list = (List<Car>) get_object_list (CAR , get_one_car);
The problem now is I'm having c compilation error for invalid conversion:
cannot convert List<object> to List<Car>
Is there anyway to fix it?
Update:
Some clarifications.
get_object_list() is in a client component, and it gets it's data from network resource (a NetStream).
object_type is being sent to the server to let it know the desired list type.
Server will reply with a Uint32 number_of_items describing the number of elements available.
then, get_one_specific_type_object() will be called number_of_items times.
It sounds like you might want to make the method generic:
List<T> GetObjectList<T>(byte objectType, Func<T> singleObjectGetter)
You'd call it as:
List<Car> cars = GetObjectList<Car>(CAR, GetOneCar);
Indeed you may well find that type inference allows you to just write:
List<Car> cars = GetObjectList(CAR, GetOneCar);
It's possible you want something like a Func<int, T> or similar - we can't really tell. It's also not clear what the first parameter is meant to be for, to be honest. If you need more detail than this, you should provide more context.
As a side note, I'd strongly encourage you to embrace C# / .NET naming conventions.
Although I imagine there should be better ways to implement your feature, this should do the trick to make your code work as it is.
List<Car> cars_list = get_object_list (CAR , get_one_car)
.Cast<Car>()
.ToList()
You may think of using IEnumerable.Cast method for this purpose.
A simple example may look like:
var objectArray = new object[]{1,2,3,4,5,8};
var intList = objectArray .Cast<int>()

Should I cast in my lambda or cast the IEnumerable?

In my project I have a MyClass which implements IMyClass. I need to return a list of IMyClass by transforming a list of other items. For simplicity's sake, assume that I can create a MyClass just by passing another item into its constructor, i.e. new MyClass(item).
Consider the following two lines, which (as far as I know) produce the same result:
var option1 = items.Select(item => new MyClass(item)).Cast<IMyClass>().ToList()
var option2 = items.Select(item => new MyClass(item) as IMyClass).ToList()
It seems to me that option #1 would require a double enumeration, once to cast all the items to my interface and once to generate the list. If I'm right then option #2 would be smarter. However, I've never seen any code using something like option #2, and I tend to assume that I'm not smart enough to come up with something clever that the rest of the C# community did not.
On a side note, I think option #2 is more aesthetically pleasing, but that's just me.
My question is: is my option #2 a better idea like I think it is? Are there are any gotchas I'm missing or other reasons why I'd want to stick with option #1? Or am I perhaps comparing two stupid ideas when there is a smarter third one that I'm missing completely?
I'd go for option 3:
var option3 = items.Select<Foo, IMyClass>(item => new MyClass(item))
.ToList()
Alternatively, don't use as but just cast normally:
var option4 = items.Select(item => (IMyClass) new MyClass(item))
.ToList()
Both of these seem cleaner than using Cast.
Oh, and as of C# 4 with .NET 4 (due to covariance), you could put a type argument on the ToList call instead:
var option5 = items.Select(item => new MyClass(item))
.ToList<IMyClass>()
It seems to me that option #1 would require a double enumeration
This is not true. In both cases, the items collection is only enumerated when you get to ToList().
The line
var option1 = items.Select(item => new MyClass(item)).Cast<IMyClass>().ToList()
is equivalent to
var option1 = items.Select(item => new MyClass(item)).Select(x => (IMyClass)x).ToList()
The only difference between the two is that the first one requires two function calls per item (unless C# inlines the lambdas somehow, which I don't believe is the case) while the second option requires only one.
Personally, I'd go with the second one as a matter of style.
Which one you use is a matter of preference, something we really cannot answer for you.
But your intuition if sort-of correct that Cast adds a second layer of iteration to your loop. It's very minor, and I doubt it will produce any measurable difference in performance, but the Cast method returns a new IEnumerable object that basically does this:
foreach (object obj in source) yield return (TResult)obj;
The effect is mostly another level on the call stack; since it uses yield it will only iterate on demand, like most other IEnumerable methods. But it will have to return though two levels of iterator state instead of one. Whether that matters for you is something you'll need to measure for your own applications.
(Also note that, at least according to the reference source, it does an unsafe cast, which might throw an exception if the cast is invalid. That's another reason to prefer your option #2.)
You can always provide explicit type arguments to your Select
var option2 = items.Select<IItem,IMyClass>(item => new MyClass(item)).ToList();
where IItem is a type or interface to which items could be cast.

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