I have a class that looks like:
public class MySuperClass
{
public void PrintValue()
{
print("SUPER Class");
}
}
I then have another class that looks like:
public class MySubClass : MySuperClass
{
public void PrintSubValue()
{
print("SUB Class");
}
}
Then, I have a situation where I have a third class that looks like:
public class MyOtherClass
{
public MyOtherClass(MySuperClass someSubClass)
{
someSubClass.PrintSubValue();
}
}
It won't compile... As is to be expected.
Now if I change MyOtherClass to look like:
public class MyOtherClass
{
public MyOtherClass(MySuperClass someSubClass)
{
someSubClass = (MySubClass) someSubClass;
someSubClass.PrintSubValue();
}
}
It still won't compile... This I didn't expect.
Why am I unable to cast a Super Class to a Sub Class? And how can I get around this issue?
Why am I unable to cast
You are able to cast, but then you assign it back to MySuperClass someSubClass which implicitly casts it back to MySuperClass.
Use
var castedSomeSubClass = (MySubClass)someSubClass;
or
MySubClass castedSomeSubClass = (MySubClass)someSubClass;
Related
This is probably a classic covariance/contravariance question, it looks like it should work but I'm probably missing a trick.
I'm attempting to return a less derived type from a factory method, but I find that I cannot cast the more specialized concrete instance to a less derived base type.
public class AnimalSettings { ... }
public class CatSettings : AnimalSettings { ... }
public interface IAnimalService<TSettings> { ... }
public abstract AnimalService<TSettings> : IAnimalService<TSettings> where TSettings : AnimalSettings { ... }
public class CatService : AnimalService<CatSettings> { ... }
Then, in a factory method I have:
public static IAnimalService<AnimalSettings> GetAnimalService(AnimalType selector)
{
switch (selector)
{
case AnimalType.Cat:
return (IAnimalService<AnimalSettings>) new CatService();
break;
}
}
and the intention is to be able to do the following:
var service = MyServiceFactory.GetAnimalService(AnimalType.Cat);
service.DoAnimalBehavior();
This compiles fine, but at runtime my code is failing in the attempted cast return (IAnimalService<AnimalSettings>) new CatService();, with an InvalidCastException.
How should I be casting my more derived type to a less derived type so that callers can use that interfaced base type to invoke functionality?
Changing the cast to (IAnimalservice<CatSettings>) new CatService() does work, but it's intended that the caller receives a IAnimalservice<AnimalSettings> so that it can handle any sort of animal (In other words, the caller should not be using any of the more specialized types). Should I be specifying an in or out as part of the generic definition somewhere?
By giving a complete example it would be much easier to help. ;-)
So here is the working code. And as Sweeper already mentioned, you need to add the out parameter at the interface to make it work.
using System;
public class Program
{
public static void Main()
{
var catService = new CatService(new CatSettings());
var genericService = (IAnimalService<AnimalSettings>)catService;
genericService.DoAnimalBehavior();
}
}
public abstract class AnimalSettings
{
public abstract void DoAnimalBehavior();
}
public class CatSettings : AnimalSettings
{
public override void DoAnimalBehavior()
{
Console.WriteLine("Meeoh");
}
}
public interface IAnimalService<out TSettings>
{
void DoAnimalBehavior();
}
public abstract class AnimalService<TSettings> : IAnimalService<TSettings> where TSettings : AnimalSettings
{
private readonly TSettings _settings;
public AnimalService(TSettings settings)
{
_settings = settings;
}
public void DoAnimalBehavior()
{
_settings.DoAnimalBehavior();
}
}
public class CatService : AnimalService<CatSettings>
{
private readonly CatSettings _catSettings;
public CatService(CatSettings catSettings)
: base(catSettings)
{
_catSettings = catSettings;
}
}
I have got two abstract classes: Particle and ParticleHub<T> where T : Particle.
I want, when I inherit Particle, for its constructor to require a ParticleHub of its respective type to be passed as a parameter. I want its constructor to be like this:
ParticleHub</*type of the inheriting class*/> _particleHub;
public Particle(ParticleHub</*type of the inheriting class*/> particleHub, OtherParameters otherParameters)
{
_particleHub = particleHub;
//use other parameters
}
If I write ParticleHub<typeof(this)> I get overloaded with errors that make me think I broke the syntax for the rest of the file. If I do ParticleHub<this.GetType()> I get the same problem, but only with fewer errors. Though with that one, I can understand that I can't use a function in a parameter type like that.
So how do I go about this?
Simple example below of an interface and generic pattern
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
IChair chair = new Chesterfield<Arm>(new Arm());
chair.Sit();
Console.Write(chair.HasSat());
}
}
public interface IChair
{
void Sit();
bool HasSat();
}
public interface IPart
{
}
public class Chesterfield<TPart> : Chair<TPart> where TPart : IPart
{
public Chesterfield(TPart part) => _part = part;
private bool _hasSat;
private readonly TPart _part;
public override void Sit()
{
_hasSat = true;
}
public override bool HasSat() => _hasSat;
}
public abstract class Chair<TPart> : IChair where TPart : IPart
{
public abstract void Sit();
public abstract bool HasSat();
}
public class Arm : IPart
{
}
public class Back : IPart
{
}
public class Leg
{
}
You have no other choise i think but to pass the type as other generic. See the exaple how it is done in terms of fluent builders as I think it is very close what You want to have: Link.
Like:
FePatricle<T, U> where T: Particle, U: FeParticle<T, U>
Looks crazy but it should do the trick in the constructor:
public FeParticle(ParticleHub<U>...
EDIT:
Or more likely as far as I understand:
FePatricle<T>: Particle where T: FeParticle<T>
So FePartivle extends Particle and it carries with itself its own type T?
Passing the inherited class itself, as below.
public abstract class Particle
{
}
public abstract class ParticleHub<T> where T : Particle
{
}
public class k1 : Particle
{
ParticleHub<k1> _particleHub = null;
public k1(ParticleHub<k1> ph)
{
_particleHub = ph;
}
}
I was using generic types in C# and I am new to using generic types. So, right now I am stuck with a problem. I have some classes like these:
public class MyModel1
{
}
public class MyModel2
{
}
public class BaseClass<T>
{
}
public class ChildClass1 : BaseClass<MyModel1>
{
}
public class ChildClass2 : BaseClass<MyModel2>
{
}
public class AnotherClass
{
//What will be the syntax of declaring this method
//The syntax of the following method is wrong and incomplete.
//It's there just to give an idea about whai i want to do.
public void MyMethod<T>()
where T : BaseClass<..what to write..>
{
}
}
My question is what will be the correct syntax of declaring MyMethod if I want to call MyMethod like this:
MyMethod<ChildClass1>();
If I understood correctly, you try to filter "MyMethod" so that T is a class of type "ChildClass ...".
You can add a generic parameter to your function like this:
public void MyMethod<T, U>()
where T : BaseClass<U>
{
}
But then you have to call MyMethod in that way.
MyMethod<ChildClass1, MyModel1>();
So it's quite complicated to use.
Another solution is to create a new "blank" class :
public abstract class Base // mark it as abstract if you don't need to use it in your code
{
}
public class MyModel1
{
}
public class MyModel2
{
}
public class BaseClass<T> : Base //The class inherits the new class
{
}
public class ChildClass1 : BaseClass<MyModel1>
{
}
public class ChildClass2 : BaseClass<MyModel2>
{
}
public class AnotherClass
{
public void MyMethod<T>()
where T : Base
{
}
}
You've forgotten to mention the return type and adding <T> after the class name. For example, if the return type is void, you could declare the method as:
public void MyMethod<T>()
where T : BaseClass<T>
{
}
This will work (by which I mean it compiles)
public void MyMethod<T>()
where T : BaseClass<MyModel1>
{ }
so does this:
public void MyMethod<T>()
where T : ChildClass1
{ }
Further edit after reading your comment...
You can do this:
public class AnotherClass<TBaseClass, TModel> where TBaseClass : BaseClass<TModel>
{
public void MyMethod(TBaseClass input)
{ }
}
I have a term for this, hopefully non-offensive. I call it The Generic Rabbit Hole of Madness. It's what happens when we try to combine generics and inheritance so that one set of classes can accomplish a broad set of goals that become increasingly confusing, and we solve it by adding more generic parameters and more generic classes.
You reach the bottom of the hole if you
- use <dynamic>
- check to see what the actual type is using GetType(), typeof, or is
- get it to compile but can't remember what it's supposed to do
Having these two methods declared in a non-generic class, which share the same signature:
private TypeResolverResult<T> TryRetrieveFromReusable<T>(TypeResolverConfiguration<T> typeResolverConfiguration) where T : class
{
return null;
}
private TypeResolverResult<T> BuildNew<T>(TypeResolverConfiguration<T> typeResolverConfiguration) where T : class
{
return null;
}
How can I create a delegate that represents these methods' signature?
I can't seem to get it, I tried:
private Func<TypeResolverConfiguration<T>, TypeResolverResult<T>> _typeResolveFunc;
But obvious this does not work because the class is non-generic and I can't change that.
Thanks
UPDATE
This is more or less what I need:
public class Manager : ATypeResolver, IManager
{
private neeedDelegate;
public Manager(RuntimeConfiguration runtimeConfiguration, IList<RepositoryContainer> repositories)
{
if (runtimeConfiguration.WhatEver)
{
neeedDelegate = TryRetrieveFromReusable;
}
else
{
neeedDelegate = BuildNew;
}
}
public override TypeResolverResult<T> Resolve<T>() where T : class
{
//Want to avoid doing this:
if (runtimeConfiguration.WhatEver)
{
TryRetrieveFromReusable(new TypeResolverConfiguration<T>());
}
else
{
BuildNew(new TypeResolverConfiguration<T>());
}
//and have just this
neeedDelegate<T>(new TypeResolverConfiguration<T>());
}
private TypeResolverResult<T> TryRetrieveFromReusable<T>(TypeResolverConfiguration<T> typeResolverConfiguration) where T : class
{
return null;
}
private TypeResolverResult<T> BuildNew<T>(TypeResolverConfiguration<T> typeResolverConfiguration) where T : class
{
return null;
}
}
Update From what I can see, an approach like this should work, as long as ATypeResolver has a where T : class on Resolve<T>:
public class Manager : ATypeResolver, IManager
{
private bool tryRetrieveFromReusable;
public Manager(RuntimeConfiguration runtimeConfiguration, IList<RepositoryContainer> repositories)
{
this.tryRetrieveFromReusable = runtimeConfiguration.WhatEver;
}
public override TypeResolverResult<T> Resolve<T>()
{
var typeResolver = tryRetrieveFromReusable ? (TypeResolver<T>)TryRetrieveFromReusable : BuildNew;
return typeResolver(new TypeResolverConfiguration<T>());
}
}
This uses a custom delegate type (a Func like you have should work too):
public delegate TypeResolverResult<T> TypeResolver<T>(
TypeResolverConfiguration<T> typeResolverConfiguration) where T : class;
If you like, you can move the var typeResolver = ... line to its own method, to separate the logic and allow you to use it from more than just Resolve. If you did that, Resolve might be as simple as: return GetTypeResolver<T>()(new TypeResolverConfiguration<T>());.
You seem to not understand exactly how generics work. I'll give a quick overview, but read the MSDN.
When you have a generic class
public class Foo<T>
{
public T Bar {get; set;}
}
And you use it something like this
Foo<int> intFoo = new Foo<int>();
Foo<string> stringFoo = new Foo<string();
At compile time, the compiler will detect the two usages of the generic type. It will create a type of each usage. So your assembly will have types that look something like this (no not exactly, but let's play pretend so that we humans can understand).
public class FooInt
{
public int Bar { get; set; }
}
public class FooString
{
public string Bar { get; set; }
}
And it will replace all uses of Foo<int> with FooInt and Foo<string> with FooString
Now if we have a non-generic class with a generic method
public class Foo
{
public T GetBar<T>() { ..... }
}
And you use it like this
Foo foo = new Foo();
int x = foo.GetBar<int>();
string s = foo.GetBar<string();
The compiler will generate
public class Foo
{
public int GetBarInt() { ..... }
public string GetBarString() { ..... }
}
And it will replace GetBar<T> with GetBarInt and GetBar<string> with GetBarString
But fields aren't like that. If you have a class that looks like so
public class Foo
{
public T Bar;
}
You cannot do this
Foo foo = new Foo();
foo.Bar<int> = 1;
foo.Bar<string> = "test";
The compiler just doesn't understand that. I'm not an expert on the internals, but my guess is that because this points to a place in memory, the compile cannot generate the generic usages at compile time.
But the point I am trying to make is this. Generics are not some magical "I don't need to specify the type" feature. They are hints to the compile that say "I am going to do this same thing multiple times, I want you to generate the code for me."
How do I implement the function defined in the interface below? When I implemented in VS2010 like I have below. MyType gets greyed out and it doesn't recongise the type anymore? thanks!
public interface IExample
{
T GetAnything<T>();
}
public class MyType
{
//getter, setter here
}
public class Get : IExample
{
public MyType GetAnything<MyType>()
{ ^^^^^^^ ^^^^^^
MyType mt = new MyType();
^^^^^^^^^^^^^^^^^^^^^^^^^^ /* all greyed out !!*/
}
}
Make a generic interface IExample<T> and then implement it using the concrete type class Get : IExample<MyType> as in the example below.
public interface IExample<T> where T : new()
{
T GetAnything();
}
public class Get : IExample<MyType>
{
public MyType GetAnything()
{
MyType mt = new MyType();
return mt;
}
}
public class MyType
{
// ...
}
Dennis' answer looks like what you want but just in case it isn't, in order to get your code working, you can do this but I'm not sure how much value this really has...
public class Get : IExample
{
public T GetAnything<T>()
{
return default(T);
}
}
public void X()
{
var get = new Get();
var mt = get.GetAnything<MyType>();
}