In a programming assignment we are not allowed to use lists, we only get to use arrays, however I have multiple classes and arrays for all of them that I want to check for a variable in them.
Foo f = new Foo();
Bar b = new Bar();
Foo[] fArray = new Foo[1];
fArray[0] = f;
CheckStatus(fArray);
public boolean CheckStatus<T>(T[] array) {
if(array[0].IsTrue()) {
return true;
}
return false;
However, I only get the issue "cannot resolve symbol "IsTrue"
I can get it to work by directly casting it to a Foo object but then it wont work with Bar etc.
It has worked great with the generics of for most other things such as extending array length but when I need to access the variables of the object I need to cast it and for that I will need specific if statements for each type of class my program has that I want to use with this method.
Thankful in advance for any help I can get here.
You will need an interface. And make your classes implement it.
public interface IMyObj
{
bool IsTrue();
}
Then constraint your T type
public boolean CheckStatus<T>(T[] array) where T : IMyObj {...}
Related
I have the follwoing:
subObject, superObject where subObject is a subclass of superObject.
I can always upcast subObject to superObject, but i cannot do the following:
wrapperObject<superObject> instance = (wrapperObject<superObject>) wrraperObject<subObject> instance2;
This is an example with generic lists:
List<Object> l1 = null;
List<Boolean> l2 = null;
l1 = (Object)l2; <<< This will not work
Object o1 = null;
Boolean o2 = false;
o1 = (Object)o2; <<< This works
I understand that in case with lists I can just iterate thru all the objects within the list and typecast them individually.
But this will not work in case of my custom class "wrapperObject"
wrapperObject<superObject> l1;
wrapperObject<subObject> l2;
l1 = (wrapperObject<superObject>)l2; <<< this doesnt work
superObject a = null;
subObject n = null;
a = (superObject)n; <<< this works
Let us assume for a moment that this would be possible
List<bool> lb = new List<bool>();
List<object> lo = (List<object>)lb;
Now, we could do
lo.Add(123); // Since lo is typed as List<object>
but lo is just a reference pointing to List<Boolean> lb. Bang!
A workaround for this type of problem is to have a base type (class or interface) that is not generic and derive a generic one from it. For instance, List<T> implements ICollection<T> which implements IEnumerable<T> which implements IEnumerable. I.e., this assignment is valid:
IEnumerable e = new List<bool>();
Note that you can do this type of conversion with arrays. I.e., you can assign
object[] obj = new Person[10];
The price we must pay for this is efficiency, since a type test is performed when we assign an array element. This type test can throw an exception if we assign a non-compatible value. See: Eric Lippert's Blog on Array Covariance
Oliver's answer is totally right, it explains why you simply can not do this. But I can think of an instructive workaround that besides helping you to achive what you want, it will help you to better understand Covariance and Contravariance in .Net. Consider the following classes:
class SuperObject { }
class SubObject : SuperObject { }
class WrapperObject<T>:IContravariantInterface<T>,ICovariantInterface<T> where T : SuperObject
{
public void DoSomeWork(T obj)
{
//todo
}
public T GetSomeData()
{
//todo
return default;
}
}
We make Wrapper implementing two interfaces: IContravariantInterface<T> and ICovariantInterface<T>. Here are they:
interface IContravariantInterface<in T> where T : SuperObject
{
void DoSomeWork(T obj);
}
interface ICovariantInterface<out T> where T : SuperObject
{
T GetSomeData();
}
By doing this we split up Wrapper functionality into two parts: a covariant one and a contravariant. Why doing this? Because by doing this we can safetly cast either from most derive classes to less ones or the other way around with the condition that we are using the right interface:
var superObjectWrapper = new WrapperObject<SuperObject>();
var subObjectWrapper = new WrapperObject<SubObject>();
ICovariantInterface<SuperObject> covariantSuperObjWrapper = subObjectWrapper;
IContravariantInterface<SuperObject> contravariantSuperObjWrapper = subObjectWrapper; //does not compile
ICovariantInterface<SubObject> covariantSubObjWrapper = superObjectWrapper; //does not compile
IContravariantInterface<SubObject> contravariantSubObjWrapper = superObjectWrapper;
By casting to these interfaces you are sure that you can only access those methods that are safe to use regarding your casting
EDIT
Base on OP's comment below consider writing converter logic in your Wrapper class. Take a look to the following refactored WrapperObject:
class WrapperObject<T> where T : SuperObject
{
private T _justATestField;
public void Copy<TType>(WrapperObject<TType> wrapper) where TType : SuperObject
{
if (wrapper._justATestField is T tField)
{
_justATestField = tField;
}
}
public WrapperObject<SuperObject> GetBaseWrapper()
{
var baseWrapper = new WrapperObject<SuperObject>();
baseWrapper.Copy(this);
return baseWrapper;
}
}
Now you can do:
var subObjectWrapper = new WrapperObject<SubObject>();
WrapperObject<SuperObject> superObjectWrapper = subObjectWrapper.GetBaseWrapper();
What you're asking about are Variant Generics. Right now, C# only allows Variant Generics on Interfaces and only in one direction. The two types of generic variance are covariance where the output of a function can be more precise than the declared variant type or contravariance where the input of a function can be less precise than the declared variant type.
If your interface needs to do both on the same variable, you're out of luck.
Long story short, I would like to be able to store generics using different type parameters in an array, by using a parent type to all the types used. MSDN mentioned it was impossible, as generics were invariant types, but a comment stated that this changed since the 4.0 framework.
Here is a basic example of what I would like to do:
public class Animal
{
}
public class Dog : Animal
{
}
public class Cat : Animal
{
}
public class MyGeneric<T>
{ }
public class MyInheritedGeneric<T> : MyGeneric<T>
{ }
static void Main(string[] args)
{
MyGeneric<Animal>[] myGenericArray = new MyGeneric<Animal>[]
{
new MyGeneric<Dog>(),
new MyInheritedGeneric<Cat>()
};
}
This returns the similar errors:
Cannot implicitly convert type
'InheritanceTest.Program.MyGeneric<InheritanceTest.Program.Dog>' to
'InheritanceTest.Program.MyGeneric<InheritanceTest.Program.Animal>'
Cannot implicitly convert type
'InheritanceTest.Program.MyInheritedGeneric<InheritanceTest.Program.Cat>'
to 'InheritanceTest.Program.MyGeneric<InheritanceTest.Program.Animal>'
Is there any way to store generics in an array using the parent class of the type, or is this simply impossible? I really hope it is possible, otherwise it will make my program a nightmare...
EDIT: A bit more context!
I am making classes to generate enemies in a game. I call them Templates (nothing to do with actual template classes, I could very well have called them Blueprints or Factories). An enemy constructor takes in a Template, which it uses to determine its own values. When the game loads, the templates are used to generate all enemies, using their Generate() function, which returns an array of the corresponding type they are assigned to produce. All the objects to be created with a template are to have a constructor taking a template as their sole parameter.
public class Template<T>
{
protected static Random random = new Random();
protected int _amount;
public int Amount
{
get { return _amount; }
}
public virtual T CreateInstance()
{
return (T)Activator.CreateInstance(typeof(T), this);
}
public virtual T[] Generate()
{
T[] objects = new T[Amount];
for (int i = 0; i < Amount; ++i)
objects[i] = CreateInstance();
return objects;
}
}
Here is a summary of the BasicZombie.cs file, which contains the actual enemy class and the template.
class Tpl_BasicZombie : Tpl_Enemy<BasicZombie>
{
public Tpl_BasicZombie()
{
_hp = 4;
_speed = 3;
_amount = 10;
}
}
class BasicZombie : GroundEnemy
{
public BasicZombie(Tpl_BasicZombie template)
: base(template, TextureManager.Get("zombie_base"), 1, 8)
{ }
public void StuffHappens()
{ }
}
When loading the game, I would like to go through all the templates in an array to load enemies from them. I know that I could do this manually, but every time I will create a new type of enemy I would need to add it manually to the code (thus probably forgetting more than once).
My two options were:
1- Use a generic, and the above problem ensues.
2- Use a non-generic, and store the type inside, which would anchor the return type Generate() function. This would mean the generate function would output an array of objects, array which would need to be converted to the suitable type every single time a template generates an array of enemies.
I have a space in my head that tells me there is an elegant solution to all this, and I hope it is right!
Yes, C# 4 supports generic variants - but only in the declarations of interfaces and delegates, so you won't be able to do it in this case. Of course you could potentially create an interface:
public interface IGeneric<out T>
and then implement that in your classes, at which point you could create an IGeneric<Animal>.
If you can give more details about what you're trying to achieve, we may be able to help you find an alternative approach.
Jon Skeet's info aside, you might be able to do something like this:
public MyGeneric<T2> ToOtherType<T2>()
{
if (typeof(T2).IsAssignableFrom(typeof(T)))
{
// todo: get the object
return null;
}
else
throw new ArgumentException();
}
new MyGeneric<Dog>().ToOtherType<Animal>(),
new MyInheritedGeneric<Cat>().ToOtherType<Animal>()
If an array is going to hold more than one type of item, the items are going to have to be stored in heap objects which are separate from the array itself (if some of the types are structs, they'll have to either be boxed or stored as a field in a generic type which derives from a non-generic one). In most cases, the simplest thing to do will be to identify a common ancestor type for everything you'll be storing in the array, and simply typecast array elements as needed. There are a few cases where that won't be feasible, however. If, for example, your collection is going to hold objects whose type is unknown but is constrained to more than one interface, it will be necessary to pass those objects to generic routines whose method type parameter is similarly constrained, and the types that may be passed to your routine have no common ancestor which satisfies all constraints, there won't be any single type to which all members of your collection can be cast that would allow them to be passed as a suitable generic.
If the objects in your collection will only be passed to a small number of routines, it may be possible to have the generic method which adds items construct delegates to suitably invoke all the necessary routines and store those delegates as part of the collection. Lambda expressions or anonymous delegates may be convenient for this.
For example, suppose one will need to be able to feed items that are stored in a list to the Wibble<T> method of various IWibbler objects and the Wobble<T> method of various IWobbler objects, where the T types have interface constraints I1 and I2.
interface IWibbler { void Wibble<T>(T param, int param) where T : I1,I2; }
interface IWobbler { void Wobble<T>(T param, string param) where T: I1,I2; }
private struct WibbleWobbleDelegateSet
{
public Action<IWibbler, int> Wibble;
public Action<IWobbler, string> Wobble;
static WibbleWobbleDelegateSet Create<T>(T param) where T: I1, I2
{
var ret = new WibbleWobbleDelegateSet ();
ret.Wibble = (IWibbler wibbler, int p2) => { wibbler.Wibble<T>(param, p2); };
ret.Wobble = (IWobbler wobbler, string p2) => { wobbler.Wobble<T>(param, p2); };
return ret;
}
}
Calling WibbleWobbleDelegateSet.Create<T>(T param), with a suitably-constrained param, will yield a non-generic structure which contains delegates that can be used to pass the parameter supplied at struct creation to any IWibbler.Wibble<T>() or IWobbler.Wobble<T>() method.
This approach is only directly usable if the list of routines that will be called is known. If one needs to be able to call arbitrary routines with constrained generic parameters, it's possible to do that either with some tricky interfaces or with Reflection, but such things get more complicated.
How Force type cast between classes of different namespaces.
Both namespaces have same class.
You can't cast an object to a type it is not. If it belongs to a different namespace then it is not the same class. You will have to create a converter:
public static Namespace1.SomeClass Convert(Namespace2.SomeClass someClass) {
Namespace1.SomeClass rtn = new Namespace1.SomeClass();
rtn.SomeProp = someClass.SomeProp;
rtn.SomeOtherProp = someClass.SomeOtherProp;
return rtn;
}
you could even use reflection to set all the properties on Namespace1.SomeClass that have the same name as Namespace2.SomeClass.
Also, if you own the code to one of the classes, you can check into overloading explicit and implicit on your class.
You can create generic Converter so you don't have to do this each time you need to cast a different type of objects,
T ConvertObject<T>(object M) where T : class
{
// Serialize the original object to json
// Desarialize the json object to the new type
var obj = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(M));
return obj;
}
// Test ObjectToCast is type Namespace1.Class, obj is Namespace2
Namespace2.Class obj = ConvertObject<Namespace2.Class>(ObjectToCast);
Assuming that both classes are the same this will work.
You can't cast from a Type to a different Type, even if the code of the class is exactly the same.
You can create a Converter capable to convert between the two types, or provide implicit/explicit casts inside both classes implementations or eventually you can try Automapper.
You need to qualify the type:
namespace Foo
{
class Bar {}
}
namespace Baz
{
class Bar {}
}
Foo.Bar x = new Foo.Bar();
Baz.Bar y = (Baz.Bar)x;
Of course, this will fail unless there is a conversion defined.
This is not possible. A type include its namespace as part of its full name.
Its like the town of Springfield: same name but from different states. They are all different.
A possible approach would be to overload the cast operator of one of the type so that they can be cast into another type. It won't be a real cast, as the result will be to create a new object with the same value.
public static explicit operator Massachusetts.Springfield(Illinois.Springfield town)
{
return new Massachusetts.Springfield(town); // or any other code to copy the fields from one type to the other
}
If both classes are serializable, you can serialize the first object to XML, change the "namespace" in the xml and deserialize it again.
The fact that the two classes have the same name doesn't mean anything to the compiler. You may have Foo.Orange and Bar.Orange, but to the compiler it may as well be Apple and Orange. To convert:
namespace Foo
{
public class Orange{}
public static explicit operator Foo.Orange(Bar.Orange) { // conversion code }
}
namespace Bar
{
public class Orange{}
public static explicit operator Bar.Orange(Foo.Orange) { // conversion code }
}
// somewhere else
Foo.Orange o = new Foo.Orange();
Bar.Orange bar = (Bar.Orange)o; // and vice-versa
I have two interfaces IHeaderRow, and IDetailRow
I then have an object that implements both RawRow:IHeaderRow, IDetailRow
I then need to cast it to HeaderRow which implements IHeaderRow.
But when I try, it ends up being null or giving an exception.
I can cast ObjectRawRow to either interface IHeaderRow, or IDetailRow
var ObjectIHeaderRow = ObjectRawRow as IHeaderRow;
var ObjectIDetailRow = ObjectRawRow as IDetailRow;
But I can not cast ObjectRawRow to HeaderRow , or ObjectIHeaderRow to HeaderRow.
It throws the error Cannot convert source type 'IA' to target type 'A'
I need to cast it into the actual class HeaderRow.
Thoughts?
EDIT:
Even though setting up an explicit cast took care of the issue I thought I'd provide an answer to the people wondering, WHY I was doing what I was.
In short, I'm sequentially processing a file. Line by line. I read the row into RawRow, and until I look at a few values, I don't actually know what type of row it is going to be. I then wanted to cast it to the proper type.
You can only implicitly cast objects to types they inherit from or implement - since RawRow doesn't derive from HeaderRow, it's not possible.
Depending on your requirements, you could overcome this by writing an explicit conversion operator, creating a HeaderRow constructor that accepts a RawRow as its prototype, or by modifying your code to operate on an IHeaderRow.
Why do you need to cast it to a HeaderRow in the first place? If IHeaderRow produced the api that a HeaderRow implements, than you should just be able to act on IHeaderRow "objects" using the defined methods.
The point of an interface is so that you can treat a grouping of different objects as a similar type. Not so that you can cast different objects between classes that are not linked by inheritance.
First, why do you need to do such a weird cast? There's probably another design for what you're trying to do.
Second, the reason you can't do the cast is because a RawRow isn't an HeaderRow. The only guarantee it makes is that it implements IHeaderRow. The problem is that it has a bunch of other stuff too, stuff that HeaderRow doesn't have. And vice versa - HeaderRow probably has a bunch of stuff that ObjectRawRow doesn't have.
Imagine your classes look like this:
interface IHeaderRow
{
string GetText();
}
class HeaderRow : IHeaderRow
{
public string GetText()
{
return "My Label";
}
public int GetFoo()
{
return 42;
}
}
class ObjectRawRow : IHeaderRow
{
public string GetText()
{
return "My Raw Label";
}
}
Now if you do this, you're ok:
ObjectRawRow row = new ObjectRawRow();
IHeaderRow header = row as IHeaderRow;
string label = header.GetText(); // fine, since GetText is guaranteed to exist
But try this on for size:
ObjectRawRow row = new ObjectRawRow();
HeaderRow header = row as HeaderRow;
int magic = header.GetFoo(); // BOOM! Method doesn't exist,
// because the object isn't really a HeaderRow under the covers.
// It's still really an ObjectRawRow. What do you do now? Crash hard is what.
And that's why you can't cast outside of the inheritance tree.
You cannot cast ObjectRawRow to HeaderRow unless one inherits from the other.
Interfaces have nothing to do with it.
Consider:
class Shape
interface IHasCorners
class Rectangle : IHasCorners, Shape
class Triangle : IHasCorners, Shape
Rectangle myRectangle = new Rectangle();
Triangle myTriangle = new Triangle();
//upcasts
Shape s = (Shape)myRectangle;
IHasCorners hc = (IHasCorners)myRectangle;
//downcasts
Rectangle r2 = (Rectangle)s;
r2 = (Rectangle)hc;
//upcasts
s = (Shape)myTriangle;
hc = (IHasCorners) myTriangle;
//these downcasts won't work
//the variables now reference a Triangle instance
Rectangle r3 = (Rectangle)s;
r3 = (Rectangle)hc;
You will not be able to make this cast unless there is an inheritance relationship between the types. If that is not possible then the best you can do is create an explicit conversion operator that allows you to cast one type as another type.
If you do create an explicit conversion you should understand that this will be slower than casting as you will be invoking an method that will do work as opposed to casting which only changes the reference type and doesn't change any of the memory on the heap.
Consider this example that doesn't compile:
class Example
{
static void Main()
{
Foo foo = new Foo();
Bar bar = (Bar)foo;
}
}
class Foo { }
class Bar { }
Since there is no inheritance relations between the types nor is there an explicit conversion from Foo to Bar this cannot compile.
But adding an explicit conversion allows it to compile:
class Example
{
static void Main()
{
Foo foo = new Foo();
Bar bar = (Bar)foo;
}
}
class Foo
{
public static explicit operator Bar(Foo foo)
{
return new Bar();
}
}
class Bar { }
You can only cast an instance to a particular class if the object is actually an instance of that class (or is derived from that class).
It is not possible to cast an instance of class A to completely unrelated class B (which is what you're trying to do), even if they implement the same interfaces.
You can use the explicit keyword to create methods that will be called when you try to cast from IA to A. The reason it doesn't work without you writing your own method is because the compiler doesn't know what to do with the values that aren't being provided.
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.