I have the following classes
public abstract class BaseViewPresenter { }
public abstract class BaseView<T> : UserControl
where T : BaseViewPresenter { }
public class LoginPresenter : BaseViewPresenter { }
public partial class LoginView : BaseView<LoginPresenter> { }
I have a method that looks like this (simplified)
public BaseView<BaseViewPresenter> Resolve(BaseViewPresenter model)
{
var type = model.GetType();
var viewType = _dataTemplates[type];
// Correctly creates BaseView object
var control = Activator.CreateInstance(viewType);
// Fails to cast as BaseView<BaseViewPresenter> so returns null
return control as BaseView<BaseViewPresenter>;
}
When I call this using an instances of LoginPresenter
var login = new LoginPresenter();
var ctl = Resolve(login);
The line Activator.CreateInstance(viewType) correctly resolves into a new instances of my LoginView, however control as BaseView<BaseViewPresenter> can't do the cast correctly so returns null.
Is there a way to correctly cast the control into BaseView<BaseViewPresenter> without using specific type generics?
Since LoginView inherits from BaseView<LoginPresenter>, and LoginPresenter inherits from BaseViewPresenter, I would assume there's a way to convert LoginView to BaseView<BaseViewPresenter>.
I am stuck with using .Net 3.5
This is a very frequently asked question. Let's rename your types:
abstract class Fruit { } // was BaseViewPresenter
abstract class FruitBowl<T> where T : Fruit // was BaseView
class Apple : Fruit { } // was LoginPresenter
class BowlOfApples : FruitBowl<Apple> { } // was LoginView
Your question now is:
I have a BowlOfApples, which inherits from FruitBowl<Apple>. Why can I not use it as a FruitBowl<Fruit>? An apple is a fruit, so a bowl of apples is a bowl of fruit.
No, it isn't. You can put a banana in a bowl of fruit, but you can't put a banana in a bowl of apples, and therefore a bowl of apples is not a bowl of fruit. (And by similar argument, a bowl of fruit is not a bowl of apples either.) Since the operations you can legally perform on the two types are different, they cannot be compatible.
Here is a photo of StackOverflow legend Jon Skeet demonstrating this fact:
The feature you want is called generic contravariance, and it is supported only on interfaces and delegate types when the compiler can prove that the variance is safe, and when the varying type is a reference type. For example, you can use an IEnumerable<Apple> in a context where IEnumerable<Fruit> is needed because the compiler can verify that there is no way that you can put a Banana into a sequence of fruit.
Do a search on "C# covariance and contravariance" on this site or on the web and you'll find many more details about how this feature works. In particular, my series of articles on how we designed and implemented this feature in C# 4 starts here: http://blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-one.aspx
I accepted Eric's answer since it provides a great explanation of why what I wanted wasn't possible, but I also thought I'd share my solution in case anyone else runs into this same problem.
I removed the generic type parameter from my original BaseView class, and created a 2nd version of the BaseView class that included the generic type parameter and specifics for it.
The first version is used by my .Resolve() method or other code that doesn't care about the specific types, and the second version is used by any code that does care, such as the implentation of a BaseView
Here's an example of how my code ended up looking
// base classes
public abstract class BaseViewPresenter { }
public abstract class BaseView : UserControl
{
public BaseViewPresenter Presenter { get; set; }
}
public abstract class BaseView<T> : BaseView
where T : BaseViewPresenter
{
public new T Presenter
{
get { return base.Presenter as T; }
set { base.Presenter = value; }
}
}
// specific classes
public class LoginPresenter : BaseViewPresenter { }
public partial class LoginView : BaseView<LoginPresenter>
{
// Can now call things like Presenter.LoginPresenterMethod()
}
// updated .Resolve method used for obtaining UI object
public BaseView Resolve(BaseViewPresenter presenter)
{
var type = model.GetType();
var viewType = _dataTemplates[type];
BaseView view = Activator.CreateInstance(viewType) as BaseView;
view.Presenter = presenter;
return view;
}
You're expecting to treat the type as being covariant with respect to the generic argument. Classes can never be covariant; you'd need to use an interface rather than (or in addition to) an abstract class to make it covariant with respect to T. You'd also need to be using C# 4.0.
My usual solution to this problem is to create an intermediary class that has access to the type-parametric class's methods through delegates. Fields can also be accessed through getters/setters.
The general pattern goes:
public abstract class Super {}
public abstract class MyAbstractType<T> where T : Super {
public MyGeneralType AsGeneralType() {
return MyGeneralType.Create(this);
}
// Depending on the context, an implicit cast operator might make things
// look nicer, though it might be too subtle to some tastes.
public static implicit operator MyGeneralType(MyAbstractType<T> t) {
return MyGeneralType.Create(t);
}
public int field;
public void MyMethod1() {}
public void MyMethod2(int argument) {}
public abstract bool MyMethod3(string argument);
}
public delegate T Getter<T>();
public delegate void Setter<T>(T value);
public delegate void MyMethod1Del();
public delegate void MyMethod2Del(int argument);
public delegate bool MyMethod3Del(string argument);
public class MyGeneralType {
public Getter<int> FieldGetter;
public Setter<int> FieldSetter;
public MyMethod1Del MyMethod1;
public MyMethod2Del MyMethod2;
public MyMethod3Del MyMethod3;
public static MyGeneralType Create<T>(MyAbstractType<T> t) where T : Super {
var g = new MyGeneralType();
g.FieldGetter = delegate { return t.field; };
g.FieldSetter = value => { t.field = value; };
g.MyMethod1 = t.MyMethod1;
g.MyMethod2 = t.MyMethod2;
g.MyMethod3 = t.MyMethod3;
return g;
}
public int field {
get { return FieldGetter(); }
set { FieldSetter(value); }
}
}
The above exemplifies getting all the methods and fields but normally I only need a few of them. This is a general solution to the problem and one could feasibly write a tool to generate these intermediary classes automatically, which I might at some point.
Try it here: https://dotnetfiddle.net/tLkmgR
Note that this is enough for all my cases, but you can be extra hacky with this:
public abstract class MyAbstractType<T> where T : Super {
// ... Same everything else ...
// data fields must become abstract getters/setters, unfortunate
public abstract int field {
get;
set;
}
public static implicit operator MyAbstractType<Super>(MyAbstractType<T> t) {
return MyGeneralType.Create(t);
}
}
public class MyGeneralType : MyAbstractType<Super> {
// ... same constructors and setter/getter
// fields but only keep method fields
// that contain the method references for
// implementations of abstract classes,
// and rename them not to clash with the
// actual method names ...
public MyMethod3Del myMethod3Ref;
// Implement abstract methods by calling the corresponding
// method references.
public override bool MyMethod3(string argument) {
return myMethod3Ref(argument);
}
// Same getters/setters but with override keyword
public override int field {
get { return FieldGetter(); }
set { FieldSetter(value); }
}
}
And there you go, now you can literally cast a MyAbstractType<Sub> where Sub : Super to a MyAbstractType<Super>, although it's no longer the same object anymore, but it does retain the same methods and data, it's sort of a complex pointer.
public class Sub : Super {}
public class MySubType : MyAbstractType<Sub> {
public int _field;
public override int field {
get { return _field; }
set { _field = value; }
}
public override bool MyMethod3(string argument) {
Console.WriteLine("hello " + argument);
return argument == "world";
}
}
public class MainClass {
public static void Main() {
MyAbstractType<Sub> sub = new MyAbstractType<Sub>();
MyAbstractType<Super> super = sub;
super.MyMethod3("hello"); // calls sub.MyMethod3();
super.field = 10; // sets sub.field
}
}
This isn't as good in my opinion, the other version of MyGeneralType is a more straighforward layer over the concrete types, plus it doesn't require rewriting the data fields, but it does actually answer the question, technically. Try it here: https://dotnetfiddle.net/S3r3ke
Example
Using these abstract classes:
public abstract class Animal {
public string name;
public Animal(string name) {
this.name = name;
}
public abstract string Sound();
}
public abstract class AnimalHouse<T> where T : Animal {
List<T> animals;
public AnimalHouse(T[] animals) {
this.animals = animals.ToList();
}
public static implicit operator GeneralAnimalHouse(AnimalHouse<T> house) {
return GeneralAnimalHouse.Create(house);
}
public List<string> HouseSounds() {
return animals.Select(animal => animal.Sound()).ToList();
}
}
We make this "general" variant:
public delegate List<string> HouseSoundsDel();
public class GeneralAnimalHouse {
public HouseSoundsDel HouseSounds;
public static GeneralAnimalHouse Create<T>(AnimalHouse<T> house) where T : Animal {
var general = new GeneralAnimalHouse();
general.HouseSounds = house.HouseSounds;
return general;
}
}
And finally with these inheritors:
public class Dog : Animal {
public Dog(string name) : base(name) {}
public override string Sound() {
return name + ": woof";
}
}
public class Cat : Animal {
public Cat(string name) : base(name) {}
public override string Sound() {
return name + ": meow";
}
}
public class DogHouse : AnimalHouse<Dog> {
public DogHouse(params Dog[] dogs) : base(dogs) {}
}
public class CatHouse : AnimalHouse<Cat> {
public CatHouse(params Cat[] cats) : base(cats) {}
}
We use it like this:
public class AnimalCity {
List<GeneralAnimalHouse> houses;
public AnimalCity(params GeneralAnimalHouse[] houses) {
this.houses = houses.ToList();
}
public List<string> CitySounds() {
var random = new Random();
return houses.SelectMany(house => house.HouseSounds())
.OrderBy(x => random.Next())
.ToList();
}
}
public class MainClass {
public static void Main() {
var fluffy = new Cat("Fluffy");
var miu = new Cat("Miu");
var snuffles = new Cat("Snuffles");
var snoopy = new Dog("Snoopy");
var marley = new Dog("Marley");
var megan = new Dog("Megan");
var catHouse = new CatHouse(fluffy, miu, snuffles);
var dogHouse = new DogHouse(snoopy, marley, megan);
var animalCity = new AnimalCity(catHouse, dogHouse);
foreach (var sound in animalCity.CitySounds()) {
Console.WriteLine(sound);
}
}
}
Output:
Miu: meow
Snoopy: woof
Snuffles: meow
Fluffy: meow
Marley: woof
Megan: woof
Notes:
I added names so it's clear that the method references carry their owner's data with them, for those unfamiliar with delegates.
The required using statements for this code are System, System.Collections.Generic, and System.Linq.
You can try it here: https://dotnetfiddle.net/6qkHL3#
A version that makes GeneralAnimalHouse a subclass of AnimalHouse<Animal> can be found here: https://dotnetfiddle.net/XS0ljg
Related
Is there a neat way to specify that a class must contain a factory method that returns the same kind of object as the class that overrides the abstract method? (Edit: Or as Johnathon Sullinger more eloquently puts it, [...] have a base class enforce a child class to implement a method that returns an instance of the child class itself, and not allow returning an instance of any other Type that inherits from the base class.)
For example, if I've got two classes, SimpleFoo : BaseFoo and FancyFoo : BaseFoo, can I define an abstract factory method public TFoo WithSomeProp(SomeProp prop) where TFoo is a type parameter that is somehow fixed by the abstract method definition to the particular class that overrides it?
I had hopes of compile-time guarantees that either
a concrete WithSomeProp method definition in SomeFoo : BaseFoo will only be able to produce SomeFoos. If static abstract method definitions were legal, perhaps the following (pseudo-syntax) method extension best expresses this need:
public static abstract TFoo WithSomeProp<TFoo>(this TFoo source, SomeProp prop)
where TFoo : BaseFoo;
I don't think this is possible in C#.
or at least some way to parameterize the return type in an abstract method, e.g.
public abstract TFoo WithSomeProp<TFoo>(SomeProp prop)
where TFoo : BaseFoo;
This wouldn't prevent FancyFoo.WithSomeProp from returning SimpleFoos, but ok.
This abstract method itself seems to work, but my concrete definition then fails:
public override SimpleFoo WithSomeProp(SomeProp prop)
{
return new SimpleFoo(this.SomeOtherProp, ..., prop);
}
with the warning
no suitable method found to override
It appears to me that specifying type parameters in an abstract method does not allow fixing them in the overrides of those definitions, but rather it specifies that "A method with a type parameter should exist".
For now I simply have public abstract BaseFoo WithSomeProp(SomeProp prop);.
It sounds like what you want to do, is have a base class enforce a child class to implement a method that returns an instance of the child class itself, and not allow returning an instance of any other Type that inherits from the base class. Unfortunately, to the best of my knowledge, that is not something you can do.
You can however force the child-class to specify what it's Type is to the base class, so that the base class can then enforce that the return value must be the Type specified by the child-class.
For instance, given a base class called BaseFactory, and BaseFactory<T>, we can create an abstract class that requires children to specify to the parent, what type the creation method returns. We include a BaseFactory class so we can constrain T to only being children classes of BaseFactory.
EDIT
I'll leave the original answer below in the event that it helps, but after some thought, I think I've got a better solution for you.
You'll still need the base class to take a generic argument that defines what the child Type is. The difference now however is that the base class has a static creation method instead of instance methods. You can use this creation method to create a new instance of the child class, and optionally invoke a callback for configuring the property values on the new instance before you return it.
public abstract class BaseFactory { }
public abstract class BaseFactory<TImpl> : BaseFactory where TImpl : BaseFactory, new()
{
public static TImpl Create(Action<TImpl> itemConfiguration = null)
{
var child = new TImpl();
itemConfiguration?.Invoke(child);
return child;
}
}
You then just create your children classes normally, without worrying about overriding any methods.
public class Foo : BaseFactory<Foo>
{
public bool IsCompleted { get; set; }
public int Percentage { get; set; }
public string Data { get; set; }
}
public class Bar : BaseFactory<Bar>
{
public string Username { get; set; }
}
Then you would use the factory as-such.
class Program
{
static void Main(string[] args)
{
// Both work
Bar bar1 = Bar.Create();
Foo foo1 = Foo.Create();
// Won't compile because of different Types.
Bar bar2 = Foo.Create();
// Allows for configuring the properties
Bar bar3 = Bar.Create(instanceBar => instanceBar.Username = "Jane Done");
Foo foo2 = Foo.Create(instanceFoo =>
{
instanceFoo.IsCompleted = true;
instanceFoo.Percentage = 100;
instanceFoo.Data = "My work here is done.";
});
}
Original Answer
The BaseFactory<T> will be reponsible for creating a new instance of TImpl and giving it back.
public abstract class BaseFactory { }
public abstract class BaseFactory<TImpl> : BaseFactory where TImpl : BaseFactory
{
public abstract TImpl WithSomeProp();
}
Now, your child class can be created, and inherit from BaseFactory<T>, telling the base class that T represents itself. This means the child can only ever return itself.
public class Foo : BaseFactory<Foo>
{
public override Foo WithSomeProp()
{
return new Foo();
}
}
public class Bar : BaseFactory<Bar>
{
public override Bar WithSomeProp()
{
return new Bar();
}
}
Then you would use it like:
class Program
{
static void Main(string[] args)
{
var obj1 = new Bar();
// Works
Bar obj2 = obj1.WithSomeProp();
// Won't compile because obj1 returns Bar.
Foo obj3 = obj1.WithSomeProp();
}
}
If you really want to make sure that the generic specified is the same as the owning Type, you could instead make WithSomeProp a protected method, so that children classes can only see it. Then, you create a public method on the base class that can do type checking.
public abstract class BaseFactory { }
public abstract class BaseFactory<TImpl> : BaseFactory where TImpl : BaseFactory
{
protected abstract TImpl WithSomeProp();
public TImpl Create()
{
Type myType = this.GetType();
if (typeof(TImpl) != myType)
{
throw new InvalidOperationException($"{myType.Name} can not create instances of itself because the generic argument it provided to the factory is of a different Type.");
}
return this.WithSomeProp();
}
}
public class Foo : BaseFactory<Foo>
{
protected override Foo WithSomeProp()
{
return new Foo();
}
}
public class Bar : BaseFactory<Bar>
{
protected override Bar WithSomeProp()
{
return new Bar();
}
}
class Program
{
static void Main(string[] args)
{
var obj1 = new Bar();
// Works
Bar obj2 = obj1.Create();
// Won't compile because obj1 returns Bar.
Foo obj3 = obj1.Create();
}
}
Now, if you create a child class that passes a different Type as T, the base class will catch it and throw an exception.
// Throws exception when BaseFactory.Create() is called, even though this compiles fine.
public class Bar : BaseFactory<Foo>
{
protected override Foo WithSomeProp()
{
return new Foo();
}
}
Not sure if this gets you what you wanted at least, but I think this will probably be the closest thing you can get.
Inspired by Johnathon Sullinger's fine answer, here is the code I ended with. (I added a theme.)
I passed the type parameter T along with the class definition and constrained that T : Base<T>.
BaseHyperLink.cs:
public abstract class BaseHyperLink<THyperLink> : Entity<int>
where THyperLink : BaseHyperLink<THyperLink>
{
protected BaseHyperLink(int? id, Uri hyperLink, ContentType contentType, DocumentType documentType)
: base(id)
{
this.HyperLink = hyperLink;
this.ContentType = contentType;
this.DocumentType = documentType;
}
public Uri HyperLink { get; }
public ContentType ContentType { get; }
public DocumentType DocumentType { get; }
public abstract THyperLink WithContentType(ContentType contentType);
}
SharedHyperLink.cs:
public sealed class SharedHyperLink : BaseHyperLink<SharedHyperLink>
{
public SharedHyperLink(int? id, Uri hyperLink, ContentType contentType, DocumentType documentType)
: base(id, hyperLink, contentType, documentType)
{
}
public override SharedHyperLink WithContentType(ContentType contentType)
{
return new SharedHyperLink(this.Id, contentType, this.DocumentType);
}
}
MarkedHyperLink.cs:
public sealed class MarkedHyperLink : BaseHyperLink<MarkedHyperLink>
{
public MarkedHyperLink(int? id, Uri hyperLink, ContentType contentType, DocumentType documentType, Mark mark)
: base(id, hyperLink, contentType, documentType)
{
this.Mark = mark;
}
public Mark Mark { get; }
public override MarkedHyperLink WithContentType(ContentType contentType)
{
return new MarkedHyperLink(this.Id, contentType, this.DocumentType, this.Mark);
}
}
I have 3 projects: 2 are class libraries and 1 is console app:
class library "AnimalManagers". In AnimalManagers is
public interface AnimalAgressiveBase{
string Bark<TAnimal>(TAnimal animal);
}
public abstract class AnimalAgressive<TEnemy> : AnimalAggresiveBase {
public abstract string BarkAtEnemy(TEnemy enemy);
public string Bark<TAnimal>(TAnimal animal){
return BarkAtEnemy((TEnemy)animal);// <---- Invalid cast exception even if type of object "animal" is Cat and we call this method from Dog class
}
}
public class AnimalManager {
public void WatchAnimal<TAnimalModel>
(TAnimalModel animalModel) { //<-- in example, animalModel is Cat("lucy")
var aggresiveAnimalDog = GetAgresiveAnimal(); //<-- returns object from dynamically loaded class Dog so this is basicaly new Dog() if animal models library class were referenced
if(aggresiveAnimalData != null) aggresiveAnimalDog .Bark(animalModel);
}
public AnimalAgressiveBase GetAgresiveAnimal(){
Assembly.LoadFrom("..\\AnimalModels.dll");
....
return aggresiveAnimal; //In This case Dog because he implements correct interface
}
}
class library "AnimalModels" In AnimalModels are model classes Cat and Dog
public class Cat {
public string Name {get;set;}
}
public class Dog : AnimalAgressive<Cat> {
public override string BarkAtEnemy(Cat enemy){return enemy.Name;}
}
Both libraries are referenced in ConsoleApp "Zoo" , and I get invalid type exception when I call
var manager = new AnimalManager();
var manager.WatchAnimal(new Cat{Name="lucy"});
I got invalid cast exception because of dynamically loaded assembly types doesnt coresspond with referenced types, even if they got same AssemblyQualifiedName.
Any solutions? Goal is to load assembly get types that implements known interface (ex: AnimalAggressiveBase) and call method that I pass data of some type.
Your main issue seems to be that you do not have anything representing your animals in the type system. How does your class Cat tie in with the rest of your class hierarchy?
public void WatchAnimal<TAnimalModel>
(TAnimalModel animalModel) { ... }
Basically here TAnimalModel can be anything; I could pass in a string an int or a Stream and the compiler wouldn't complain. You need to constaint TAnimalModel to what you are really expecting so that the compiler can reason about what you can do or not do with animalModel:
public void WatchAnimal<TAnimalModel>
(TAnimalModel animalModel) { ... } where TAnimalModel: AnimalBase
AnimalBase can be an abstract base class, a regular base class, an interface, what have you. The only condition is that all your animal models need to implement it:
public class Cat: AnimalBase { ... }.
The same thing happens with the following method:
public abstract class AnimalAgressive<TEnemy> : AnimalAggresiveBase { ... }
Again, here TEnemy can be anything. That is why you are getting a compile time error in (TEnemy)animal. The compiler can't verify that the cast is valid and therefore disallows it; you know that TEnemy will be an animal but you haven't told the compiler... so tell the compiler adding a constaint:
public abstract class AnimalAgressive<TEnemy> : AnimalAggresiveBase where TEnemy: AnimalBase { ... }
Performance expensive solution IMHO.
[EDIT TO CLASS]
public abstract class AnimalAgressive<TEnemy> : AnimalAggresiveBase where TEnemy : class, new(){
[EDIT TO METHOD]
public string Bark<TAnimal>(TAnimal animal){
var typeAnimal = typeof(TAnimal);
var typeEnemy = typeof(TEnemy);
var propsAnimal = typeData.GetProperties();
var propsEnemy = typeGener.GetProperties();
var obj = new T();
foreach (var propertyInfo in propsAnimal)
{
var value = propertyInfo.GetValue(dataObject);
try
{
var propEnemy = propsEnemy.FirstOrDefault(x => x.Name.Equals(propertyInfo.Name, StringComparison.CurrentCulture));
propGener?.SetValue(obj, value, null);
}
catch (Exception)
{
throw;
}
}
return Bark(obj.Name);
I would recommed MEF here.
public interface IAnimalAgressive<in TAnimal>
{
string Bark(TAnimal animal);
}
public abstract class AnimalAggressiveBase<TEnemy> : IAnimalAgressive<TEnemy>
{
public abstract string BarkAtEnemy(TEnemy enemy);
public string Bark(TEnemy enemy)
{
return BarkAtEnemy(enemy);
}
}
your Animal manager then becomes:
public class AnimalManager
{
public void WatchAnimal<TAggressiveAnimal, TAnimal>
(TAggressiveAnimal aggressive, TAnimal enemy)
where TAggressiveAnimal : IAnimalAgressive<TAnimal>
{
Console.WriteLine(aggressive.Bark(enemy));
}
}
Now its the responsibility of the Dog and Cat to conform to the AnimalManager expectations, I will keep it simple for now:
using System.ComponentModel.Composition;
namespace AnimalModels
{
[Export(typeof(Cat))]
public class Cat
{
public string Name { get; set; }
}
}
and Dog becomes:
using AnimalManagers;
using System.ComponentModel.Composition;
namespace AnimalModels
{
[Export(typeof(AnimalAggressiveBase<Cat>))]
public class Dog : AnimalAggressiveBase<Cat>
{
public override string BarkAtEnemy(Cat enemy)
{
return enemy.Name;
}
}
}
The trick now is to compose the whole catalog of relevant types, so for our console app, we create another type for managing these relationships from the catalog of types we have exported:
public class TypeManager
{
public void Compose()
{
try
{
var directoryPath = Path.GetFullPath(".");
var aggregateCatalog = new AggregateCatalog();
aggregateCatalog.Catalogs.Add(new DirectoryCatalog(directoryPath, "*.dll"));
//Create the composition container
var container = new CompositionContainer(aggregateCatalog);
container.ComposeParts(this);
var cat = container.GetExportedValue<Cat>();
cat.Name = "lucy";
var dog = container.GetExportedValue<AnimalAggressiveBase<Cat>>();
var manager = new AnimalManager();
manager.WatchAnimal(dog, cat);
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
throw;
}
}
}
now all we need to do is to run the Main method like this:
static void Main(string[] args)
{
TypeManager tm = new TypeManager();
tm.Compose();
}
Now the exported types will automatically get created in the typemanager and we dont have to worry about reflection.
public interface AnimalAgressiveBase<TAnimal>
{
string Bark(TAnimal animal);
}
public abstract class AnimalAgressive<TEnemy, TAnimal> : AnimalAgressiveBase<TAnimal> where TEnemy : TAnimal
{
public abstract string BarkAtEnemy(TEnemy enemy);
public string Bark(TAnimal animal)
{
return BarkAtEnemy((TEnemy)animal);
}
}
I have 2 classes:
public class Articles
{
private string name;
public Articles(string name)
{
this.name = name;
}
public void Output()
{
Console.WriteLine("The class is: " + this.GetType());
Console.WriteLine("The name is: " + name);
}
}
And
public class Questionnaire
{
private string name;
public Questionnaire(string name)
{
this.name = name;
}
public void Output()
{
Console.WriteLine("The class is: " + this.GetType());
Console.WriteLine("The name is: " + name);
}
}
I want to write a method, that takes an integer (1 meaning Articles should be returned, 2 meaning Questionnaire) and a name.
This method must return an instance of one of those two classes:
public [What type??] Choose(int x, string name)
{
if (x == 1)
{
Articles art = new Articles(name);
return art;
}
if (x == 2)
{
Questionnaire ques = new Questionnaire(name);
return ques;
}
}
What return type should I use, so I can call Output() on the result?
Why not have a base class that has Output defined. Then return the base.
public abstract class BaseType {
public abstract void Output();
}
Both Articles and Questionaire should inherit this BaseType.
public class Articles : BaseType {
// Output method here
}
public class Questionaire : BaseType {
// Output method here
}
Then you can do:
public static BaseType Choose(int x, string name)
{
if (x == 1)
{
Articles art = new Articles(name);
return art;
}
if (x == 2)
{
Questionnaire ques = new Questionnaire(name);
return ques;
}
}
You could also achieve this via an interface.
public interface IInterface {
void Output();
}
public class Articles : IInterface {
// Output method here
}
public class Questionaire : IInterface {
// Output method here
}
You would then have to modify the Choose method to return IInterface rather than BaseType. Whichever you choose is up to you.
Note: even if you can't change original classes you can still use these approaches before resorting to dynamic by providing wrapper classes that implement the interface and either inherits original or forwards calls to corresponding method:
public class ArticlesProxy : Articles, IInterface
{
public ArticlesProxy(string name) : base(name){}
}
public class QuestionaireProxy : Questionaire, IInterface {
Questionaire inner;
public QuestionaireProxy(string name) { inner = new Questionaire(name); }
public void Output() { inner.Output();}
}
How about something like this:
public interface IHasOutput
{
void Output();
}
public class Articles : IHasOutput
public class Questionnaire : IHasOutput
and then:
public static IHasOutput Choose...
You can of course call your interface anything you'd like, other than IHasOutput, I just don't know what to call it. This is what interfaces are for. Two different concrete implementations that share a common interface. Now when you call it you can do this:
var entity = MyClass.Choose(1, "MyName");
entity.Output();
and it doesn't matter what concrete implementation is returned. You know it implements a common interface.
Answers provided here are great but one thing I don't like is parameter x that chooses what type should be created. That creates use of magic number, which may become head-ache even for you later.
You can take advantage of generics here, i.e. make method Choose:
public static T Choose<T>(string name)
// type constraint to ensure hierarchy.
where T : BaseClass // BaseClass have common functionality of both class.
{
// Unfortunately you can't create instance with generic and pass arguments
// to ctor. So you have to use Activator here.
return (T)Activator.CreateInstance(typeof(T), new[] { name });
}
Usage:
Articles article = ClassWithChooseMethod.Choose<Articles>("name");
Questionnaire questionnaire = ClassWithChooseMethod.Choose<Questionnaire>("name2");
Demo
Edit
As #OlivierJacot-Descombes mentioned in comment x that chooses type might be user-input. In that case you can create enum with respective values:
enum ArticleType {
Articles = 1,
Questionnaire = 2
}
And have overload of Choose:
public static BaseClass Choose(ArticleType type, string name) {
switch (type) {
case ArticleType.Articles:
return ClassWithChooseMethod.Choose<Articles>(name);
case ArticleType.Questionnaire:
return ClassWithChooseMethod.Choose<Questionnaire>(name);
default:
return default(BaseClass);
}
}
and usage:
var obj = ClassWithChooseMethod.Choose((ArticleType)userInput, "some name");
This gives you possibility to keep your code cleaner and useful for future maintenance (e.g. you can change logic of class creation in Choose).
P.S. You might be interested to read more about factory pattern.
Unless they share the same base class or interface, you're pretty much stuck with either object or dynamic.
The most flexible way to solve this problem is to write an interface as well as an abstract base class implementing it. This way you have the freedom to derive a class from the base class or to implement the interface directly, if the base class does not satisfy your needs in a very special case or if a class derives from another class already. Also make the method Output virtual; this enables you to override it if necessary. Also make the name protected; this enables you to use it in derived classes
public interface IHasOutput
{
void Output();
}
public abstract class OutputBase : IHasOutput
{
protected string _name;
public OutputBase(string name)
{
_name = name;
}
#region IHasOutput Members
public virtual void Output()
{
Console.WriteLine("The class is: " + this.GetType());
Console.WriteLine("The name is: " + _name);
}
#endregion
public static IHasOutput Choose(int x, string name)
{
switch (x) {
case 1:
return new Articles(name);
case 2:
return new Questionnaire(name);
default:
return null;
}
}
}
public class Articles : OutputBase
{
public Articles(string name)
: base(name)
{
}
}
public class Questionnaire : OutputBase
{
public Questionnaire(string name)
: base(name)
{
}
}
UPDATE
Another very simple way to solve the problem is to override ToString:
public override string ToString()
{
return String.Format("The class is: {0}\r\nThe name is: {1}",
this.GetType(), _name);
}
You would call it like this:
object obj = Factory.Choose(1, "Test");
Console.WriteLine(obj);
No interface and no base class required! Well, to be precise, the base class is object of course.
You have 3 choices:
1) Make Questionnaire and Article inherit from the same base class and make the type of that base class be the return type of your method.
2) Make your return type Object.
3) Make your return type Dynamic.
I'd appreciate your advice on the following:
I'm using polymorphism. I have a base class and 30 sub classes that inherit this base class. I'm up casting instances of these sub classes to the base class type so that they can be handled in a more generic fashion.
My question is this.
I need to access a public property that is specific to a particular sub class. Do I need to write a giant case statement where I check the type and down cast accordingly in order to access the property I need or is there a more elegant solution?
static void Main(string[] args)
{
animal slyvester = new cat();
animal lassie = new dog();
animal silver = new horse();
// Big ugly type checking code. If I have 30 types to check is there a better way?
if (slyvester.GetType() == typeof(cat)) {
Console.WriteLine(((cat)(animal)slyvester).PurrStrength);
}
else if(slyvester.GetType() == typeof(dog)) {
}
else if (slyvester.GetType() == typeof(horse))
{
}
Console.ReadLine();
}
}
public class animal {
}
public class cat : animal {
private string _purrStrength = "Teeth Shattering";
public string PurrStrength {
get { return _purrStrength; }
set { _purrStrength = value; }
}
}
public class dog : animal {
}
public class horse : animal {
}
You should consider an interface based approach. With interfaces, you define a set of operations (a contract by which implementers must conform) which your types must define. E.g, we could define a base interface, IAnimal
public interface IAnimal
{
string GetSound();
}
From which we can define some animal types:
public class Cat : IAnimal
{
public string GetSound()
{
return "Meow!";
}
}
public class Dog : IAnimal
{
public string GetSound()
{
return "Woof!";
}
}
Now, when we want to declare our animal, we declare it of type IAnimal:
IAnimal cat = new Cat();
IAnimal dog = new Dog();
Console.WriteLine(cat.GetSound());
Console.WriteLine(dog.GetSound());
You could go one step further, and specialise your animals:
public class Cat : IAnimal
{
public virtual string GetSound()
{
return "Meow!";
}
}
public class BigCat : Cat
{
public override string GetSound()
{
return "Roar!";
}
}
In the latter example, I can make a default implementation of the cat's GetSound method, and then override it for my big cat.
Interface based programming hides away the need to horrible type conversions, because an interface guarantees a set of operations that will be provided.
If you don't have to know the exact type of the passed object, you just need a property value in case it doesn't exist in the base type, but it may or may not exists in the actual type, you can use reflection:
static void Main(string[] args)
{
animal slyvester = new cat();
animal lassie = new dog();
animal silver = new horse();
DoSomething(slyvester);
DoSomething(lassie);
DoSomething(silver);
Console.ReadLine();
}
static void DoSomething(animal entity)
{
string INeedThisProperty = "PurrStrength";
Type type = entity.GetType();
PropertyInfo property = type.GetProperty(INeedThisProperty);
if (property != null && property.CanRead)
{
Console.WriteLine("Found: {0}", property.GetValue(entity, null));
}
}
If in precise moment of property access you dont't have any clue what type is it, somehow you have to figure out it.
Or, what I personaly would do, is try to create virtual functions/properties on base class that describes my child classes action in more generic way, override them in child classes with concrete implementation and after call that functions/properties using upper casted objects.
The answer is to use polymorphism. The idea is to introduce a method in the base interface or as in this case the base class. Then just call this method! The runtime will automagically delegate the call to the correct type.
Look at the modified implementation below:
public abstract class Animal
{
public abstract void OutputInterestingFact();
}
public class Cat : Animal {
private string _purrStrength = "Teeth Shattering";
public string PurrStrength {
get { return _purrStrength; }
set { _purrStrength = value; }
}
public override void OutputInterestingFact()
{
Console.WriteLine(PurrStrength);
}
}
public class Dog : Animal {
public override void OutputInterestingFact()
{
// Do stuff for dog here
}
}
public class Horse : Animal {
public override void OutputInterestingFact()
{
// Do stuff for horse here
}
}
I made the Animal into an abstract class. You could also make the OutputInterestingFact method virtual with an empty method body.
I've also renamed your classes to begin with an upper case letter. Make this a habit since this is practice in C# and other programmers will find your code easier to read.
Now, to use this just call the method.
slyvester.OutputInterestingFact();
Is that elegant enough?
Your code does not cover all the cases that I can think of, but just 2 possible solutions:
class Animal {
public abstract string PropertyValue { get; set; }
}
class Cat : Animal {
public override string PropertyValue {
get { return PurrStrength; }
set { PurrStrength = value; }
}
}
or, for multiple properties:
class Animal {
public virtual string[] GetPropertyValues() { return null; }
}
class Cat : Animal {
public override string[] GetPropertyValues() {
return new string[] { PurrStrength };
}
}
In my app, I have deal with several different "parameters", which derive from IParameter interface, and also ParamBase abstract base class. I currently have two different parameter types, call them FooParameter and BarParameter, which both derive from ParamBase. Obviously, I can treat them both as IParameters when I need to deal with them generically, or detect their specific type when I need to handle their specific functionality.
My question lies in specific FooParameters. I currently have a few specific ones with their own classes which derive from FooParameter, we'll call them FP12, FP13, FP14, etc. These all have certain characteristics, which make me treat them differently in the UI. (Most have names associated with the individual bits, or ranges of bits). Note that these specific, derived FP's have no additional data associated with them, only properties (which refer to the same data in different ways) or methods.
Now, I'd like to keep all of these parameters in a Dictionary<String, IParameter> for easy generic access. The problem is, if I want to refer to a specific one with the special GUI functions, I can't write:
FP12 fp12 = (FP12)paramList["FP12"] because you can't downcast to a derived type (rightfully so). But in my case, I didn't add any data, so the cast would theoretically work.
What type of programming model should I be using instead? Thanks!
There's nothing really wrong with this approach, except for maybe storing the parameters in a dictionary. What is the purpose of doing that? Especially if you key them on their class name.
I would just use a List<IParameter> and have a control go through the collection and pick the right subclass out of there.
m_Parameters = new List<IParameter>();
//This control needs FP12
foreach(var param in Parameters) {
var fp12 = param as FP12;
if (fp12 != null) {
//do something with the param.
break;
}
}
After writing the above I think I finally understand what you are trying to do. If you want to perform an operation that is available on FP12 on any subclass of FooParameter then you need to take that operation out of FooParameter altogether. Since your parameter is data and that data is the same across different subclasses of FooParameter, it makes sense to only have one implementation of FooParameter ("data" class) and multiple "operation" classes.
//The one implementation of IParameter for all FooParameters
public class FooParameter : IParameter {
string Data1 {get;set;}
}
//base class for Foo Operation, only stores FooParameter
public class FooOperationBase {
protected readonly FooParameter m_Param;
public FooOperationBase (FooParameter param) {
m_Param = param;
}
}
//specific operations on FooParameter go in this class
public class FooOperation12 : FooOperationBase {
public FooOperation12(FooParameter param) : base(param) {}
public void DoSomeOperation() {
return m_Param.Data1 + " transformed";
}
}
If paramList["FP12"] is a FP12, that cast will work. Of course, if it's not it will throw a InvalidCastException. You could also use as, if you're not sure what type the object will be.
Whether this is an ideal design is a separate issue. Ideally, you want to prefer polymorphism, meaning the subclass of FooParameter knows to use its new special functions internally, and the outside code doesn't have to cast, or use as or is.
I'm not 100% sure where you're coming from with this question, but you could do something like this:
class Program
{
static void Main(string[] args)
{
var paramList = new List<IParameter>();
paramList.Add(new FooParameter());
paramList.Add(new BarParameter());
paramList.Add(new F1());
paramList.Add(new F2());
foreach (var p in paramList)
{
p.DoCommonOperation();
DoSpecificOperation(p);
}
Console.ReadKey();
}
private static void DoSpecificOperation(IParameter p)
{
if (p is F1)
{
(p as F1).F1Method();
}
else if (p is F2)
{
(p as F2).F2Method();
}
}
interface IParameter
{
void DoCommonOperation();
}
abstract class ParamBase : IParameter
{
public virtual void DoCommonOperation()
{
Console.WriteLine("ParamBase");
}
}
class FooParameter : ParamBase
{
public override void DoCommonOperation()
{
Console.WriteLine("FooParameter");
}
}
class BarParameter : ParamBase
{
public override void DoCommonOperation()
{
Console.WriteLine("BarParameter");
}
}
class F1 : FooParameter
{
public override void DoCommonOperation()
{
Console.WriteLine("F1");
}
public void F1Method()
{
Console.WriteLine("F1.F1Method");
}
}
class F2 : FooParameter
{
public override void DoCommonOperation()
{
Console.WriteLine("F2");
}
public void F2Method()
{
Console.WriteLine("F2.F2Method");
}
}
}
Essentially you have a method in the class that controls the list of IParameter objects that knows how to call the specific implementations, and uses is/as to do so.
Just for sanity's sake, why not use Dictionary<Type, IParameter>? With a little generics, you could do this:
public interface IParameter { }
public class FP12 : IParameter { public string fieldFP12 { get; set; } }
public class FP11 : IParameter { public string fieldFP11 { get; set; } }
public static class DictionaryHelper
{
public static T GetParameter<T>(this Dictionary<System.Type,
IParameter> target) where T : IParameter
{
return (T)target[typeof(T)];
}
}
Sample program and output:
class Program
{
static void Main()
{
Dictionary<Type, IParameter> parameters =
new Dictionary<Type, IParameter>();
parameters.Add(typeof(FP12), new FP12 { fieldFP12 = "This is FP12" });
parameters.Add(typeof(FP11), new FP11 { fieldFP11 = "This is FP11"});
// THIS IS WHERE YOU GET THE IPARAMETER YOU WANT - THE GENERICS WAY...
var fp12 = parameters.GetParameter<FP12>();
var fp11 = parameters.GetParameter<FP11>();
Console.WriteLine(fp12.fieldFP12);
Console.WriteLine(fp11.fieldFP11);
Console.ReadLine();
}
}
The resulting output:
This is FP12
This is FP11