3

I have 2 different projects in my solution.

In one I have a class called MyClass1, and in the other I have MyClass2 These classes are identical in all but name.

In one project I have a list of Objects. During runtime the list gets filled with MyClass1 objects that we casted to an object.

At the end I want to cast each object in the list to a MyClass2 object.

Currently it throws an exception saying Unable to cast object of type MyClass1 to MyClass2.

My Code:

List<Object> _tempObjects = new List<Objects>();
foreach(Object myObjectInput in _tempObjects)
{
  MyClass2 temp = (MyClass2) myObjectInput; // here is where it dies
}

The two classes are the same, just different names. I have also tried:

 MyClass2 temp = myObjectInput as MyClass2; 
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
John
  • 175
  • 2
  • 8
  • 4
    what you are trying to do is not possible – thumbmunkeys Sep 29 '14 at 15:19
  • Is MyClass1 a subclass of MyClass2, or the other way around? – Yann Sep 29 '14 at 15:19
  • What is the error you get at "here is where it dies"? – Leo Chapiro Sep 29 '14 at 15:20
  • It doesn't matter if it same or not when the there is two names – huMpty duMpty Sep 29 '14 at 15:20
  • 1
    The name of the class make them completely different things to the compiler. The only way to allow for casting from one type to the other in this case is to define your own custom cast method. This can be implicit or explicit. But you still cannot cast from object to a different type, unless you define the cast from object. – Jeffrey Wieder Sep 29 '14 at 15:25
  • 1
    Use an interface, or a base (abstract) class. Define you list with the type of interface/class and then you can call your methods normally. Look it up how interfaces work. – Measurity Sep 29 '14 at 15:33

8 Answers8

12

What you are trying to do is not possible. Even though the classes have the same contents, they are still different types.

What you can do is:

  • create an interface with all the things that are shared among the 2 types
  • let your 2 types implement that interface
  • cast to this interface when you get the object out of the list
thumbmunkeys
  • 20,606
  • 8
  • 62
  • 110
11

Casting doesn't work that way. When casting (an object statically known as) object to another type, it must already be an instance of that type for it to work. Maybe you'd like to convert from one to the other with AutoMapper, e.g.

Mapper.CreateMap<MyClass1, MyClass2>();

// later...
MyClass2 temp = Mapper.Map<MyClass2>(myObjectInput);

Or manually copy the properties, maybe in a constructor:

public MyClass2(MyClass1 other)
{
    this.SomeProperty = other.SomeProperty;
    // etc
}

MyClass2 temp = new MyClass2((MyClass1)myObjectInput);

More likely, what you should do is make the projects share MyClass in a way that .NET understands and supports natively: by putting it in a project that can be referenced by both projects. If one project should reference the other, do that; otherwise, create a third project as a library.

Tim S.
  • 55,448
  • 7
  • 96
  • 122
6

You can't simply cast one type to another without an explicit (or implicit) cast operator being implemented.

First, i'd question why you have two identical classes at all. But, if this must be done, you'll have to declare an explicit cast conversion between one to the other:

public class Class1
{
    public string Name { get; set; }

    public static explicit operator Class1(Class2 cls)
    {
        return new Class1 { Name = cls.Name };
    }
}

public class Class2
{
    public string Name { get; set; }

    public static explicit operator Class2(Class1 cls)
    {
        return new Class2 { Name = cls.Name };
    }
}
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
  • Note that these cast operators require that the compiler knows that the old object was that type, not just an `object` (as the asker's code is). If he had the (more sensible) `List`, etc. this would be a working answer. – Tim S. Sep 29 '14 at 15:26
  • FWIW, I dislike cast operators, except in certain scenarios like numeric types: Besides the limitation from my last comment, compared to a static method, they are less discoverable (no IntelliSense), easier to mess up in refactoring, and less type safe (since they share syntax with the nearly-universal casting). I've seen it recommended that they're paired with a static method that does the same thing, which usually leaves me saying, "I'm going to use the static method and don't need the conversion, after all." – Tim S. Sep 29 '14 at 15:31
  • 1
    Right. This is assuming the OP has an instance of either type – Yuval Itzchakov Sep 29 '14 at 15:32
  • @TimS. I disagree on the second comment. I've found them useful in a project where a certain type was an extension of another, yet there was no inheritance relationship between the two. The existence of the cast operator makes sense when you need to convert one type to another IMO. Practically, it's doing the same thing you're doing with the static `Mapper.Map` method. – Yuval Itzchakov Sep 29 '14 at 15:48
  • note that under the covers, the cast conversion is just a static method called by the compiler when it sees the applicable code. Consider if you, e.g. changed it to `public Class1(Class2 cls)` (or a `static` method) and `(Class1)myCls` to `new Class1(myCls)`: you have to be more explicit and a little more verbose to do the same thing, but with the benefits I mentioned. – Tim S. Sep 29 '14 at 16:15
  • 1
    Yeah, i understand regarding the static method. I guess its a matter of taste. – Yuval Itzchakov Sep 29 '14 at 16:27
1

These classes are identical in all but name.

Nope. That's not how static typing works. The classes may be intuitively similar when looking at their implementation, but as far as the compiler is concerned they are entirely different. One can not be directly cast to another.

List<Object> _tempObjects = new List<Objects>();

This adds a third type to the mix, Object. A List<Object> can contain anything as far as the compiler is concerned, it's not limited to your two classes. So that definitely can't be cast to an instance of your class.

If your two projects need to use the same type, extract that type into a common project and your two projects can reference that common project. Then you can just use that type everywhere:

List<MyClass1> _tempObjects = new List<MyClass1>();
David
  • 208,112
  • 36
  • 198
  • 279
0

You can't cast objects just because their implemented identically. They must either inherit from the same baseclass or from the same interface, or be a subclass of each other (and then you can only cast from child to parent class).

hometoast
  • 11,522
  • 5
  • 41
  • 58
0

In one I have a class called MyClass1, and in the other I have MyClass2 These classes are identical in all but name.

But MyClass1 is not MyClass2 and MyClass2 is not MyClass1. You cannot cast one to the other. You need to map them. Basically for each property, set the value from one instance to another.

TyCobb
  • 8,909
  • 1
  • 33
  • 53
0

You can not cast these two objects, even if they have same implementation, before you implement explicit cast operator or or type is the one ur current type is derivative from/to. Here is a cheat sheet of casting in .NET, look please http://www.codeproject.com/Articles/5044/Cheat-Sheet-Casting-in-VB-NET-and-C

prvit
  • 956
  • 3
  • 9
  • 22
0

If MyClass1 and MyClass2 are meant to be similar, you could introduce an interface (let's call is IMyClass) and have MyClass1 and MyClass2 implement said interface and then your code (modified below) would work by casting to the shared interface.

foreach(Object myObjectInput in _tempObjects)
{
  IMyClass temp = (IMyClass) myObjectInput;
}
Babak Naffas
  • 12,395
  • 3
  • 34
  • 49