The following code throws an InvalidCastException.
public static MachineProductCollection MachineProductsForMachine(
MachineProductCollection MachineProductList, int MachineID)
{
return (MachineProductCollection)
MachineProductList.FindAll(c => c.MachineID == MachineID);
}
This surprises me since MachineProductCollection is merely a generic List of MachineProducts which is exactly what FindAll() should return. Here’s the full MachineProductCollection source code. You will note is merely a wrapper for List.
[Serializable]
public partial class MachineProductCollection :
List<MachineProduct>
{
public MachineProductCollection() { }
}
I resorted to the following which basically loops through the FindAll() result which is of type List and adds each item to my MachineProductCollection. Obviously, I don’t like the required iteration.
public static MachineProductCollection
MachineProductForMachine(MachineProductCollection
MachineProductList, int MachineID)
{
MachineProductCollection result =
new MachineProductCollection();
foreach (MachineProduct machineProduct in
MachineProductList.FindAll(c => c.MachineID == MachineID))
{
result.Add(machineProduct);
}
return result;
}
Documentation states an InvalidCastException is thrown when a failure occurs during an explicit reference conversion. Reference conversions are conversions from one reference type to another. While they may change the type of the reference, they never change the type or value of the conversion’s target. Casting objects from one type to another is a frequent cause for this exception.
Considering List is MachineProductCollection’s base, should this really be an InvalidCastException?
Yes, the invalid cast exception is correct. You can freely cast from a derived class to a base class but you cannot blindly cast from a base class to a derived class unless the object really is an instance of the derived class. It's the same reason you cannot do this:
object obj = new object();
string str = (string) obj;
Right? object is string's base, and you cannot freely cast from object to string. On the other hand this would work since obj is indeed a string:
object obj = "foo";
string str = (string) obj;
You're getting the InvalidCastException because a List<MachineProduct> isn't necessarily a MachineProductCollection, even though the reverse is obviously true.
The simplest solution to return an actual MachineProductCollection would be to use List<T>'s sequence constructor:
public static MachineProductCollection
MachineProductForMachine(MachineProductCollection MachineProductList, int MachineID)
{
List<MachineProduct> found =
MachineProductList.FindAll(c => c.MachineID == MachineID))
return new MachineProductCollection(found);
}
However, since you're using lambda expressions I'm guessing you have access to LINQ (via .NET 3.5 or LINQ Bridge), which means you can use the Where extension method to skip the intermediate list:
public static MachineProductCollection
MachineProductForMachine(MachineProductCollection MachineProductList, int MachineID)
{
IEnumerable<MachineProduct> found =
MachineProductList.Where(c => c.MachineID == MachineID))
return new MachineProductCollection(found);
}
That said, you might be better off just returning an IEnumerable<MachineProduct> rather than creating your own collection type. This will probably make your life easier unless you're planning to add special logic to your MachineProductCollection. And in that case, you could always just write extension methods against IEnumerable<MachineProduct> to provide that logic. Just some things to consider...
Related
I'm trying to create an instance of specified Type whatever user wants to have. For a quick illustration of my purpose please see the code below:
static void Main(string[] args)
{
object o = GetInstance(typeof(int));
Console.WriteLine("Created type: {0}", o.GetType().FullName);
}
public static object GetInstance(Type t)
{
Console.WriteLine("Creating instance of {0}", t.FullName);
return Activator.CreateInstance(t);
}
The problem is Activator.CreateInstance() returns object by default. There is also an overload of this method like T Activator.CreateInstance<T>() which is parameterless and returns the type you specify as T.
However, the problem is T should be hard-coded while calling this method and thus should be a fixed value. I am trying to create an instance of desired class and return it as its type.
Right now if you use this method you should write something like:
int i = GetInstance(typeof(int)) as int
I'm trying to reduce this to:
int i = GetInstance(typeof(int))
Is there a way that I can do casting inside the GetInstance and get rid of that as int repetition? By this way, my return type (and also the type I cast the object to) will be unknown at compile time.
Seemed impossible by design to me but I'd really appreciate if you figure it out.
EDIT: Where I'm stuck is e.g. while you're casting, you can do return (T) result if you are in a generic method, but you can't do Type t = ...; return (t) result this doesn't work. You cannot cast to a type which is passed to you as a parameter which is not known at compile time.
Follow a known pattern
This is not a new problem. It is a problem facing any API that allows type-specific return values. For example, a JSON parsing library like Newtonsoft (which is, to wit, the single most popular .NET package downloaded by .NET programmers in 2019) must be able to parse a string and return a type-specific object, which may or may not be known at compile time. It might make sense to follow their example.
Newtonsoft exposes three ways to specify the type when deserializing. You could do as you are currently doing:
//Cast required
var result = JsonConvert.DeserializeObject(text, typeof(MyType)) as MyType;
You can use a generic method:
//No cast required, but you have to hardcode a type as a type parameter
var result = JsonConvert.DeserializeObject<MyType>(text);
Or you can use an instance as a template, which is great for anonymous types, although you can use it with non-anonymous classes as well. This one works via generic type inference:
//No cast required and no need to specify type; the type is inferred from the argument
var result = JsonConvert.DeserializeAnonymousType(text, new MyType());
Here's how you'd do it:
So for you to make this work, your code might look like this:
public object GetInstance(Type type)
{
return Activator.CreateInstance(type);
}
int i = GetInstance(typeof(int)) as int;
public T GetInstance<T>()
{
return Activator.CreateInstance<T>();
}
int i = GetInstance<int>();
public T GetInstance<T>(T template)
{
return Activator.CreateInstance<T>();
}
int i = GetInstance(0);
If you do it this way, it's hard to imagine any programmer would have trouble using your library, as the approach should already be familiar to them.
Actually you could write GetInstance like this:
static T GetInstance<T>()
{
return Activator.CreateInstance<T>();
}
And use it:
int j = GetInstance<int>();
This might help you to create instance of desired type:
public class ConcreteFactory<T> : AbstractFactory<T>
{
public override T CreateInstance(string typeName,params object[] parameters)
{
var path = Assembly.GetExecutingAssembly().CodeBase;
var assembly = Assembly.LoadFrom(path);
var type = assembly.GetTypes().SingleOrDefault(t => t.Name == typeName);
return (T)Activator.CreateInstance(type, parameters);
}
}
Key here is generic type T can be used to cast the created instance, this can be used as a template to create instance of any type with parameterized constructor
I'm writting a c# code generator. In some place I must cast return type of Linq's method like WhereSelectListIterator to IEnumerable type. How can I do it?
Scenario:
I have an instance of a List named aList. I write following expression in a Textbox:
aList.Where(item => item.StartsWith("s")).Select(item => item.ToUpper()).ToList().Count
I need to write an application to evaluate my expression. I know that i must write an C# code generator to evaluate my expression.
If I evaluate above expression directly it is works. But suppose that I have following scenario :
public Interface IInterface
{
}
public class MyClass:IInterface
{
public int Id = 10;
public IInterface GetInstance()
{
return new MyClass();
}
}
public class Program
{
public static void Main()
{
var myClass = new MyClass();
myClass.GetInstance().Id.ToString();
}
}
When I use Id property after calling GetInstance() method it cause to CLR raise an exception because IInterface hasn't Id property. I need to cast return type of GetInstance() to MyClass first then use Id property.
How can I do this cast dynamically.
One solution is using dynamic object.
var myClass = new MyClass();
dynamic x = myClass.GetInstance();
dynamic y = myClass.Id;
y.ToString();
But dynamic object has problem with Extension methods(ex : Where(), Take() , ...). What can I do?
In answer to the question you ask in the title, The result of Enumerable<T>.Where(Predicate) implements IEnumerable<T>, just cast it, no need to do anything fancy. See here: Enumerable..Where(TSource) Method (IEnumerable(TSource), Func(TSource, Boolean))
As for the rest, why are you trying to generate C# code? If you're trying to evaluate a code snippet that was entered at runtime, why not use the C# compiler to compile it? I Googled for "C# programmatic compilation", and the first result was this Microsoft support page: How to programmatically compile code using C# compiler
You can call extension methods on dynamic objects like this:
dynamic result = Enumerable.Where(collection, (Func<dynamic, bool>)delegate(dynamic item)
{
return item.Id == id;
});
WARNING: THIS CODE SUCKS, SEE ANTHONY'S COMMENTS
Which is faster?
1.
public bool IsValueType<T>(T obj){
return obj is ValueType;
}
2.
public bool IsValueType<T>(T obj){
return obj == null ? false : obj.GetType().IsValueType;
}
3.
public bool IsValueType<T>(T obj){
return default(T) != null;
}
4.Something else
You aren't really testing an object - you want to test the type. To call those, the caller must know the type, but... meh. Given a signature <T>(T obj) the only sane answer is:
public bool IsValueType<T>() {
return typeof(T).IsValueType;
}
or if we want to use an example object for type inference purposes:
public bool IsValueType<T>(T obj) {
return typeof(T).IsValueType;
}
this doesn't need boxing (GetType() is boxing), and doesn't have problems with Nullable<T>. A more interesting case is when you are passing object...
public bool IsValueType(object obj);
here, we already have massive problems with null, since that could be an empty Nullable<T> (a struct) or a class. But A reasonable attempt would be:
public bool IsValueType(object obj) {
return obj != null && obj.GetType().IsValueType;
}
but note that it is incorrect (and unfixable) for empty Nullable<T>s. Here it becomes pointless to worry about boxing as we are already boxed.
My first answer would be to write a simple test and find out for yourself.
My second answer (without any testing on my part, of course) would be option 1. It is the simplest check. The second method involves two separate checks while the third involves creating a default instance of a type.
You should also consider readability. The framework already gives you the ability to have the following in your code:
if(someObj is ValueType)
{
// Do some work
}
Why even bother creating a method that would simply turn the above statement into (assuming you made your method static and allowed the compiler to infer the generic type):
if(IsValueType(someObj))
{
// Do some work
}
Defining a struct actually defines two types: a value type, and a class type which derives from System.ValueType. If a request is made to create a variable, parameter, field, or array (collectively, 'storage location') of a type which derives from System.ValueType, the system will instead create a storage location which will store the object's fields rather than storing a reference to an object in which those fields appear. On the other hand, if a request is made to create an instance of a type deriving from System.ValueType, the system will create an object instance of a class which derives from System.ValueType.
This may be demonstrated by creating a struct which implements IValue:
interface IValue {int value {get; set;}};
struct ValueStruct : IValue
{
public int value {get; set;}};
}
with generic test routine and code to wrap it:
static void Test<T>(T it) where T:IValue
{
T duplicate = it;
it.value += 1;
duplicate.value += 10;
Console.WriteLine(it.value.ToString());
}
static void Test()
{
ValueStruct v1 = new ValueStruct();
v1.value = 9;
IValue v2 = v1;
Test<ValueStruct>(v1);
Test<ValueStruct>(v1);
Test<IValue>(v1);
Test<IValue>(v1);
Test<IValue>(v2);
Test<IValue>(v2);
}
Note that in every case, calling GetType on the parameter passed to Test would yield ValueStruct, which will report itself as a value type. Nonetheless, the passed-in item will only be a "real" value type on the first two calls. On the third and fourth calls, it will really be a class type, as demonstrated by the fact that a change to duplicate will affect it. And on the fifth and sixth calls, the change will be propagated back to v2, so the second call will "see" it.
static class Metadata<T>
{
static public readonly Type Type = typeof(T);
static public readonly bool IsValueType = Metadata<T>.Type.IsValueType;
}
//fast test if T is ValueType
if(Metadata<T>.IsValueType) //only read static readonly field!
{
//...
}
There are two rules:
1-All Classes are reference types such as Object and String, so it's supported by .NET Framework classes.
2-All structures are value types such as bool and char, even though it contain reference member, so it's supported by .NET Framework structures.
Simply right click on any type and Go To Definition if it's a Class so that means it a reference type else if it's a Struct so that means it's a value type :)
You can use
obj.GetType().IsValueType
This uses reflection but clear way instead of care of boxing unboxing.
To convert between some LINQ to SQL objects and DTOs we have created explicit cast operators on the DTOs. That way we can do the following:
DTOType MyDTO = (LinqToSQLType)MyLinq2SQLObj;
This works well.
However when you try to cast using the LINQ .Cast() extension method it trows an invalid cast exception saying cannot cast type Linq2SQLType to type DTOType. i.e. the below does not work
List<DTO.Name> Names = dbContact.tNames.Cast<DTO.Name>()
.ToList();
But the below works fine:
DAL.tName MyDalName = new DAL.tName();
DTO.Name MyDTOName = (DTO.Name)MyDalName;
and the below also works fine
List<DTO.Name> Names = dbContact.tNames.Select(name => (DTO.Name)name)
.ToList();
Why does the .Cast() extension method throw an invalid cast exception? I have used the .Cast() extension method in this way many times in the past and when you are casting something like a base type to a derived type it works fine, but falls over when the object has an explicit cast operator.
The Cast<> extension method does not apply user-defined conversions. It can only cast to interfaces or within the class heirarchy of the supplied type.
User defined conversions are identified at compile time based on the static types involved in the expression. They cannot be applied as runtime conversions, so the following is illegal:
public class SomeType
{
public static implicit operator OtherType(SomeType s)
{
return new OtherType();
}
}
public class OtherType { }
object x = new SomeType();
OtherType y = (OtherType)x; // will fail at runtime
It doesn't matter whether a UDC exists from SomeType to OtherType - it cannot be applied through a reference of type object. Trying to run the above code would fail at runtime, reporting something like:
System.InvalidCastException:
Unable to cast object of type 'SomeType' to type 'OtherType'
Cast<>() can only perform representation preserving conversions ... that's why you can't use it to apply user-defined conversions.
Eric Lippert has a great article about the behavior of the cast operator in C# - always a worthwhile read.
If you decompile the Linq assembly you get code resembling the following. The previous answer is correct, ultimately the cast is from 'object' to target-type which will always fail for custom types.
private static IEnumerable<TResult> CastIterator<TResult>( IEnumerable source )
{
foreach(object current in source)
{
yield return (TResult)( (object)current );
}
yield break;
}
public static IEnumerable<TResult> DCast<TResult>( this IEnumerable source )
{
IEnumerable<TResult> enumerable = source as IEnumerable<TResult>;
if(enumerable != null)
{
return enumerable;
}
if(source == null)
{
throw new ArgumentNullException( "source" );
}
return CastIterator<TResult>( source );
}
TFish
For those that hit this question looking for a workaround...
Dim res = arrayOfStrings.Select(Function(__) CType( __, YourType ))
Not sure the exact semantics with C#, but i'm sure it's pretty easy.
I am having a problem with the return type of a method.
The method returns a linq object which at present returns type tblAppointment. This method is shown below:
public tblAppointment GetAppointment(int id)
{
var singleAppointment = (from a in dc.tblAppointments
where a.appID == id
select a).SingleOrDefault();
return singleAppointment;
}
The problem is that tblAppointment is abstract and has many sub types that inherit it. When I try and return an object that is of Type "appointmentTypeA" and call the .GetType() method on it, it gives me the correct sub type, but when i try and access the properties it only allows me to access the parent properties. If i take the object and cast it to a new object of the subtype then it works and lets me access everything i need but it seems messy.
var viewSingleAppointment = appointmentRepos.GetAppointment(appointmentId);
Debug.Write(viewSingleAppointment.GetType()); //returns type i want
if (viewSingleAppointment is tblSingleBirthAppointment)
{
tblSingleBirthAppointment myApp = (tblSingleBirthAppointment)viewSingleAppointment; //need to do this to access TypeA properties for some reason
}
Edit: I have got this working but I need to use a select statement for each appointment (about 20) and cast them to the appropriate type and retreive the properties and im not sure how to refactor this as it will be used on a few pages we are doing.
You're solving the wrong problem. If you have a superclass A, with subclasses B, C, etc., that all have similar functionality, you want to do the following:
Make A an interface that B, C, etc. implement. Code that works with B or C instances does by working through the interface provided by A. If you can define a common set of operations that work on all the types, then this is all you need to do.
If you can't define a common set of operations, e.g. you have code similar to:
A foo = GetA();
if(foo is B) {
B bFoo = (B) foo;
// Do something with foo as a B
} else if(foo is C) {
C cFoo = (C) foo;
// Do something with foo as a C
} ...
Or even this (which is basically the same thing, just using extra information to emulate what the type system already provides for you):
A foo = GetA();
MyEnum enumeratedValue = foo.GetEnumeratedValue();
switch(enumeratedValue) {
case MyEnum.B:
B bFoo = (B) foo;
// Do something with foo as a B
break;
case MyEnum.C:
C cFoo = (C) foo;
// Do something with foo as a C
break;
}
Then what you really want is to do something like:
A foo = GetA();
foo.DoSomething();
Where each subclass would implement the corresponding branch of the switch statement. This is actually better in several ways:
It uses less overall code.
Since the implementations of the cases live in the various implementation classes, no casting is necessary; they can access all the member variables directly.
Since you're not building a big switch/case block separate from the actual B and C implementations, you don't run any risk of accidentally forgetting to add a corresponding case if add a new subclass. If you leave the DoSomething() method out of a subclass of A, you will get a compile-time error.
Edit: In response to your comment:
If your DoSomething() routine needs to operate on a Form or other GUI element, just pass that element into the method. For example:
public class B : A {
public void DoSomething(MyForm form) {
form.MyLabel.Text = "I'm a B object!";
}
}
public class C : A {
public void DoSomething(MyForm form) {
form.MyLabel.Text = "I'm a C object!";
}
}
// elsewhere, in a method of MyForm:
A foo = GetA();
foo.DoSomething(this);
Alternatively, an even better idea might be to turn your B and C classes into custom controls, since they seem to encapsulate display logic.
Well, if you're using C# 4 you could use dynamic typing... but if you want to stick to static typing, I suspect the best you can do is provide the expected type as a generic type argument, and get the method to perform the cast for you:
public T GetAppointment<T>(int id) where T : tblAppointment
{
var singleAppointment = (from a in dc.tblAppointments
where a.appID == id
select a).SingleOrDefault();
return (T) singleAppointment;
}
Call this with:
SpecificAppointment app = GetAppointment<SpecificAppointment>(10);
or use implicit typing:
var app = GetAppointment<SpecificAppointment>(10);
It will throw an exception at execution time if the cast fails.
This assumes the caller knows the appointment type (although they could specify tblAppointment if they don't). Without knowing the appropriate appointment type at compile-time it's hard to see how static typing can do you any more favours, really...
You could create a generic method :
public T GetAppointment<T>(int id) where T : tblAppointment
{
var singleAppointment = dc.tblAppointments.SingleOrDefault(a => a.appID == id);
return (T)singleAppointment;
}
But then you would need to know the object's actual type before calling it...
When you call .GetType(), you get the runtime type of the object. C# compiler doesn't know what runtime type your object will have. It only knows that your object is going to be of a type derived from tblAppointment because you said so in your method declaration, so the static type of the return value is tblAppointment. Therefore tblAppointment is all you can access, unless you use a cast to tell the compiler «I know that at runtime this reference is going to refer to an object of this type, insert a runtime check and give me a reference with this static type».
Static typing is all about the difference between types as known at compile time and as they are at runtime. If you come from a dynamically typed language like Smalltalk or Javascript, you'll have to make quite a few adjustments to your programming habits and thought processes. E.g., if you have to do something to an object that depends on its runtime type, the solution often is to use virtual functions — they dispatch on the object's runtime type.
Update: in your particular case, use virtual functions, this is exactly what they were made for:
class tblAppointment
{
protected abstract void ProcessAppointment () ;
}
sealed class tblBirthAppointment
{
protected override void ProcessAppointment ()
{
// `this` is guaranteed to be tblBirthAppointment
// do whatever you need
}
}
...
Then use
// will dispatch on runtime type
appointmentsRepo.GetAppointment (id).ProcessAppointment () ;
You could create another method to encapsulate the cast:
public tblSingleBirthAppointment GetBirthAppointment(int id)
{
var singleAppointment = GetAppointment(id);
if (singleAppointment != null)
{
return (tblSingleBirthAppointment)singleAppointment;
}
return null;
}
That method would break if you tried to use it with an ID that wasn't actually a BirthAppointment though, so you might consider checking.
var viewSingleBirthAppointment = appointmentRepos.GetBirthAppointment(appointmentId);
If you are returning reference to a child type that is a parent type, the reference will be of that type and the compiler will not allow you to access any of the child type's members until you cast to that type. This is polymorphism in action :)
The good news is that you are not creating a new object when you cast a reference type - you are simply changing the type of the reference that points to the object you already have thereby giving you access to its members.