How to return dynamic return types in methods? C#
c#, generics, linq-to-sql, return-type
Solution
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.
Problem
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.