If I have the following code:
public abstract BaseClass
{
public void SendName(<Take in an interface>)
{ // Do stuff }
}
public class Derived : BaseClass, IMyProperties
{
public string IMyProperties.Name { get; set; }
public void Derived()
{
IProperties.Name = "Dave";
}
public void SendNameToBase
{
base.SendName(//I want to send IProperties);
}
}
How do I send IProperties to the base class?
Your base class's method should be defined like such:
public void SendName(IProperties props)
{ // Do stuff }
You call this method from the child class like this: (assuming you want to pass the current instance of the your child class, since it implements IProperties)
base.SendName(this);
Note: I'm also assuming that IMyProperties == IProperties in your code example.
well since you explicitly setup the interface, you would have to do
base.SendName((IMyProperties)this);
What exactly do you mean by sending an interface?
If you want to pass the type statically, you can use a generic (i.e. templated) method:
public void SendName<T>(T properties)
where T : IProperties // types passed in must derive from IProperties
{
var name = properties.Name;
// ...
}
//...
// Usage:
base.SendName<IProperties>(this);
If you want to send the type at runtime, you can pass around Type objects:
public void SendName(Type type)
{ /* Do stuff */ }
//...
// Usage:
base.SendName(typeof(IProperties));
I am not sure what you are trying to accomplish, but maybe if you declared the variable in the base clase you would be able to access IProperties in both functions
public abstract BaseClass
{
public string IMyProperties.Name { get; set; }
public void SendName(<Take in an interface>)
{ // Do stuff }
}
Related
is there a method to tell a method which type a generic has? what i want to do is to tell the method it can be only an object of type A or B but nothing else, so i can work within like
if (myObject.GetType() == typeof(myTypeA)){doAstuff();}
if (myObjectGetType() == typeof(myTypeB)) {doBstuff();}
method<T>(T myObject){ T = myTypeA, T = myTypeB, T = nothing else}
thanks for any help
You could check for the type inside the method, then cast it to the appropriate type and do the appropriate "stuff":
public void method<T>(T myObject)
{
if (myObject is myTypeA)
{
myTypeA objA = myObject as myTypeA;
objA.DoA_Stuff();
}
else if (myObject is myTypeB)
{
myTypeB objB = myObject as myTypeB;
objB.DoB_Stuff();
}
else
{
return ;
}
}
But that would be a waste of generics. If they share some methods you could also make a base class, and let typeA and typeB inherit from it. Then your method could take a base class object as parameter:
public void method(BaseClass myObject)
and there would be only one if - case and one casting. Only the one with more methods then the base class.
EDIT:
Imagine you would have such a structure:
public class BaseType
{
public int SharedProp { get; set; } // shared property
public virtual int DoSharedStuff() // shared method
{
return SharedProp;
}
}
public class myTypeA : BaseType
{
public int A_Prop { get; set; }
// overwritten shared meth adjusted to the needs of type A
public override int DoSharedStuff()
{
return base.SharedProp + this.A_Prop;
}
}
public class myTypeB : BaseType
{
public int B_Prop { get; set; }
// overwritten shared meth adjusted to the needs of type B
public override int DoSharedStuff()
{
return base.SharedProp + this.B_Prop;
}
// individual method of Type B
public int DoB_Stuff()
{
return this.B_Prop;
}
}
Then you method would take only one of the children of the base class and execute according to the needs:
public void method(BaseType myObject)
{
// shared case: here type A will perform type A action
// and type B will perform type B action
myObject.DoSharedStuff();
// case B where you need really the extra stuff!
if (myObject is myTypeB)
{
myTypeB objB = myObject as myTypeB;
objB.DoB_Stuff();
}
}
This approach or phenomenon is called Polymorphism
You can restrict the allowed types for a gernic with the where command:
public void Test<T>(T param) where T : TypeA {
...
}
https://learn.microsoft.com/de-de/dotnet/csharp/language-reference/keywords/where-generic-type-constraint
But this are only simple constraints so it does not solve the problem for two classes but for this case you can use method overloading:
public void Test(TypeA param) {
...
}
public void Test(TypeB param) {
...
}
If you have only two classes I think that is the best solution because generics would have no benefits.
I have the following classes:
public interface IService
{
void ApplyChanges<T>(T parameters) where T : ParamBase;
}
public class ServiceBase : IService
{
public virtual void ApplyChanges<T>(T parameters) where T : ParamBase
{ }
}
public abstract class Service : ServiceBase
{
public override void ApplyChanges<T>(T parameters) where T : ParamBase
{
Console.WriteLine(parameters.Param2);
//Apply changes logic here...
}
}
public abstract class ParamBase
{
public string Param1 { get; set; }
}
public class ParamA : ParamBase
{
public string Param2 { get; set; }
}
Here my test main class:
void Main()
{
var service = new Service();
var paramA = new ParamA();
paramA.Param2 = "Test2";
service.ApplyChanges<ParamA>(paramA);
}
What is wrong with that implementation? How can I access parameters.Param2from the overriden ApplyChanges method in my Service class?
The general idea is that I have a ServiceBase and I want to be able for its derived classes to pass different parameter types to the ApplyChanges method.
I'm making a leap here, but it sounds like you intend to have multiple "services", each with an associated parameter type.
Putting a type parameter on the method, as you have done in the example, forces all implementations of that method to be polymorphic. (The technical term for this is higher-rank quantification.)
Instead, you should associate the type parameter with the service itself. This allows a given implementation of the contract to declare which parameter type it's associated with. While you're at it, I wouldn't bother with the base classes or the type bounds.
interface IService<in T>
{
void ApplyChanges(T param);
}
class Param1
{
public int X { get; set; }
}
class Service1 : IService<Param1>
{
public void ApplyChanges(Param1 param)
{
param.X = 123;
}
}
class Param2
{
public int Y { get; set; }
}
class Service2 : IService<Param2>
{
public void ApplyChanges(Param2 param)
{
param.Y = 456;
}
}
You shouldnt impose stronger constraints for method overrides. An overridden method should expand the possible input parameters and reduce the possible outcomes. Otherwise it breaks Liskov Substitution Principle. C# does not allow you to do that.
That said, if you really want it, you could. You won't get compiler warnings in the calling code though. Use that solution if you cannot change the base class.
public class Service<TParam> : Service where TParam : ParamA
{
public override void ApplyChanges<T>(T parameters)
{
Console.WriteLine((parameters as TParam).Param2);
}
}
A better solution would be to add a type parameter to ServiceBase and IService.
public interface IService<TParam>
where TParam : ParamBase
{
void ApplyChanges(TParam parameters);
}
public abstract class ServiceBase<TParam> : IService<TParam>
where TParam : ParamBase
{
public virtual void ApplyChanges(TParam parameters)
{ }
}
public class Service : ServiceBase<ParamA>
{
public override void ApplyChanges(ParamA parameters)
{
Console.WriteLine(parameters.Param2);
}
}
Really, instead of replacing the interface's generic type, it is cleaner to use a "Type Guard". I say cleaner because the interface's method signature stays consistent, and really, what's more important than how your interface is used? (Obviously puppies are more important)
Within the method itself, you can make sure that the type is the one desired as such...
public void Method(ParentRequest req){
if(req is ChildRequest request){
//Do logic here
} else {
throw new Exception($"request is of type {req.GetType().Name} and must be of type ParentRequest");
}
}
I'm trying to setup some classes like:
public abstract class AnimalBase {
public string SpeciesName { get; private set; }
public AnimalBase(string speciesName) {
this.SpeciesName = speciesName;
}
public abstract void CopyFrom(AnimalDefaultClass defaultVals);
}
public class Mammal : AnimalBase {
public bool WalksUpright { get; private set; }
public Mammal(string speciesName) : base(speciesName) {
this.CopyFrom(new MammalDefaultClass(speciesName));
}
public override void CopyFrom(MammalDefaultClass defaultVals) {
this.WalksUpright = defaultVals.WalksUpright;
}
public void Cripple() {
this.WalksUpright = false;
}
}
public class MammalDefaultClass : AnimalDefaultClass {
public bool WalksUpright { get; private set; }
public MammalDefaultClass(string speciesName) {
using (var dataStore = theoreticalFactory.GetDataStore()) {
this.WalksUpright = dataStore[speciesName].WalksUpright;
}
}
}
Obviously that's not quite what I'm trying to accomplish, but the idea is:
Several classes (Mammal, Fish, Insect, etc) which inherit from an abstract base (Animal).
Each child class has a corresponding class it can use (in this case to populate mutable default values) as a parameter for a method which was defined as abstract in the base class.
Each of those corresponding classes (MammalDefaultClass, FishDefaultClass, InsectDefaultClass, etc) inherit from a common base class (AnimalDefaultClass).
Those AnimalDefaultClass derivatives exist because each class of Animal will have different properties, but by definition there will always be a class capable of getting those values for any Animal.
My problem is:
That overridden version of CopyFrom(MammalDefaultClass) isn't being recognized as a valid override of the abstract CopyFrom(AnimalDefaultClass), even though MammalDefaultClass inherits from AnimalDefaultClass
Is it possible to specify a base class as an abstract member's parameter? Is there a simple* workaround? Or is this whole thing just laid out wrong?
-edit: my resolution-
After playing around some with MWB and sza's suggestions, I ended up having each subclass implement the method using the base parameter and then cast the input as appropriate, something like:
public class Mammal : AnimalBase {
...
// implements the abstract method from the base class:
public override void CopyFrom(AnimalDefaultClass defaultVals) {
this.CopyFrom((MammalDefaultClass)defaultVals);
}
public void CopyFrom(MammalDefaultClass defaultVals) {
this.WalksUpright = defaultVals.WalksUpright;
}
}
This solution forces me to always implement a CopyFrom(AnimalDefaultClass) , which was the point of the putting the abstract method in the base class in the first place.
I think you can try Abstract Factory pattern. Basically you want to handle some construction logic during the creating the object, and for each different subtype of the Product, you can do differently.
public abstract class AnimalBase
{
public string SpeciesName { get; private set; }
protected AnimalBase(string speciesName)
{
this.SpeciesName = speciesName;
}
}
public class Mammal : AnimalBase
{
public bool WalksUpright { get; set; }
public Mammal(string speciesName) : base(speciesName)
{
}
public void Cripple()
{
this.WalksUpright = false;
}
}
public interface IAnimalFactory<T> where T : AnimalBase
{
T CreateAnAnimal(string speciesName);
}
public class MammalFactory: IAnimalFactory<Mammal>
{
public Mammal CreateAnAnimal(string speciesName)
{
var mammal = new Mammal(speciesName);
var mammalDefault = new MammalDefaultClass(speciesName);
mammal.WalksUpright = mammalDefault.WalksUpright;
return mammal;
}
}
And when you want to create a sub-typed object, you can do e.g.
var mammalFactory = new MammalFactory();
var bunny = mammalFactory.CreateAnAnimal("Bunny");
So it turns out that even though MammalDefaultClass is a subclass of AnimalDefaultClass, you cannot override a function that takes an AnimalDefaultClass with one that takes a MammalDefaultClass.
Consider this block of code:
public class Dinosaur : AnimalDefaultClass;
Dinosaur defaultDinosaur;
public void makeDinosaur(AnimalDefaultClass adc)
{
adc.CopyFrom(defaultDinosaur);
}
MammalDefaultClass m;
makeDinosaur(m);
In this case MammalDefaultClass is a subclass of AnimalDefaultClass, so m can be passed to makeDinosaur as adc. Furthermore the CopyFrom for an AnimalDefaultClass only needs another AnimalDefault class, so I can pass in a dinosaur. But that class is actually a Mammal, and so needs a MammalDefaultClass, which dinosaur is not.
The work around would be to take the original type signature and throw an error if the argument is the wrong type (similar to how arrays act in Java).
I am trying to create a class based on an abstract class and overwrite a function contained in the base class with another one that has a return type of "T" which is a type passed by the class.
e.g:
public abstract class DayInfo
{
public virtual void GetInfo()
{
throw new NotImplementedException();
}
}
public class DayInfo<T> : DayInfo
{
private T info;
public DayInfo(T data)
{
info = data;
}
public T GetInfo() // << This
{
return info;
}
}
Examples:
1
DayInfo info = new DayInfo<String>("Blah");
String stuff = info.GetInfo();
2
DayInfo info = new DayInfo<int>(25);
int stuff = info.GetInfo();
Is there any way to achieve this?
Edit 1:
I forgot to precise that I didn't used a class-passed type in the base class because I wanted to be able to use it as a generic type without having to define any type.
e.g:
public SortedDictionary<int, DayInfo> Data = new SortedDictionary<int, DayInfo>();
Edit 2:
Also, the point of the virtual function in the base class is that it will make the child classes throw an exception if the GetInfo() function is accessed but isn't overridden.
this is the way to achieve your goal:
public abstract class DayInfoA<T>
{
public virtual T GetInfo()
{
.......
}
}
public class DayInfoB<T> : DayInfoA<T>
{
private T info;
public DayInfoB(T data)
{
info = data;
}
public override T GetInfo() // << This
{
.........
}
}
and use it like this:
DayInfoB<int> info = new DayInfoB<int>(25);
int stuff = info.GetInfo();
Why dont you declare GetInfo() as dynamic?
This way the casting should be automatic. The only downside is that you'd lost the compiler assertions and if the variable that stores GetInfo() value can't do the cast, it'll throw a runtime error.
For example:
public abstract class DayInfo {
public abstract dynamic GetInfo();
}
public class DayInfo<T> : DayInfo {
private readonly T _info;
public DayInfo(T info) {
_info = info;
}
public override dynamic GetInfo() {
return _info;
}
}
You also could declare something like GetInfo<T>(ref T result), this way you can omit the T type from the method call and let the compiler infer it at runtime, the only downside is that you should pass the variable to store the result as an argument instead to get it returned by the method.
This can be produced with NVI pattern:
public abstract class DayInfo
{
protected virtual void GetInfoCore() {
throw new NotImplementedException();
}
// or
// protected abstract void GetInfoCore();
public void GetInfo() {
GetInfoCore();
}
}
public class DayInfo<T> : DayInfo
{
private T info;
public DayInfo(T data) {
info = data;
}
public new T GetInfo() { // << This
return info;
}
protected override void GetInfoCore() {
GetInfo();
}
}
No, not like it looks like you're wanting it (assuming you don't want to or cant alter the base class declaration). In order for the function to resolve to a polymorphic call, you need to have the same signature and return type. Otherwise it wont resolve the function polymorphically, it'll just call the base class version of the function since that's what it sees you calling (and the variable you've assigned your instance to is of the base class type).
You CAN do this, but it's pretty ugly:
DayInfo info = new DayInfo<String>("Blah");
String stuff = ((DayInfo<string>)info).GetInfo();
No, because the functions won't match up with different function signatures.
What you can do is define it like so:
public abstract class DayInfo
{
public virtual object GetInfo()
{
throw new NotImplementedException();
}
}
and in the derived class like this:
public object GetInfo() // << This
{
return info;
}
Then they would both have the same signature and the polymorphism would match up.
However, on the other end a cast will be required:
DayInfo info = new DayInfo<int>(25);
int stuff = (int)info.GetInfo();
Edit: As an aside unless there's more to it I'd make that into an interface or if the GetInfo really does nothing make the GetInfo purely abstract.
public abstract object GetInfo();
You could create a covariant interface instead of, or in addition to, a base class:
void Main()
{
IDayInfo dayInfo = new DayInfo<string>("hi!");
object info = dayInfo.GetInfo(); //info == "hi!"
}
public interface IDayInfo
{
object GetInfo();
}
public interface IDayInfo<out T> : IDayInfo
{
new T GetInfo();
}
public class DayInfo<T> : IDayInfo<T>
{
private T info;
public DayInfo(T data)
{
info = data;
}
public T GetInfo()
{
return info;
}
object IDayInfo.GetInfo()
{
return this.GetInfo();
}
}
(see Variance in Generic Interfaces for info on what covariance/contravariance are)
Note that object info (in my second line in Main) is as precise as you can get without casting in this example. Once you store the DayInfo<string> object in an IDayInfo<object> variable/field, as I did (and as you'd like to do in your dictionary), the stronger typing of string is, in a sense, forgotten and cannot be restored without a cast.
Update: added IDayInfo interface.
I have the following abstract class:
public abstract class BaseClass{
public object contents { get; set; }
public Action<BaseClass> mutator;
public abstract void Initialise();
}
This will be used by several classes, which will override the Initialize method to assign a value to contents, which will in turn be mutated using the mutator delegate at specific points in time.
I have the following static class, with each method intended to be used as a mutator:
public static class Mutators{
public static void VariantA(A inputObj){
// inputObj.contents = something else
}
public static void VariantB(A inputObj) { } // etc. etc.
}
I then have class A, which implements BaseClass. I am trying to assign Mutators.VariantA to the mutator delegate, but i'm not able to.
public class A : BaseClass{
public A(){
mutator = Mutators.VariantA;
}
public override void Initialise(){
/* set the value of contents property here */
}
}
Specifically I get the following error: A method or delegateMutators.VariantA(A)' parameters do not match delegate System.Action<BaseClass>(BaseClass)' parameters (CS0123)
I understand that Mutators.VariantA(A) requires an object of type A, and the Action was declared to accept an input of type BaseClass, however as class A implements BaseClass I thought I would have been able to do this ?
Coming from dynamically typed languages i'm having a tough time getting to grips with working with types in this way :(
Is there any way I can point to a function with an input of the abstract type in this way ? Do I need to look at some other design pattern ?
Thanks
I understand that Mutators.VariantA(A) requires an object of type A, and the Action was declared to accept an input of type BaseClass, however as class A implements BaseClass I thought I would have been able to do this ?
Absolutely not.
An Action<BaseClass> has to be able to accept any BaseClass object. So for example, if your code were valid, I would be able to write:
Action<BaseClass> mutator = Mutators.VariantA;
mutator.Invoke(new B());
(Where B is another class derived from BaseClass.)
The fact that B derives from BaseClass makes it valid for the invocation - but it's not going to help your VariantA method work nicely.
It's not really clear why you have a mutator here - I strongly suspect you should abstract BaseClass from its mutations. I still don't follow what you're trying to achieve, but this design pattern isn't going to help you get there in a type-safe way.
You could write:
public abstract class BaseClass<T> where T : BaseClass<T> {
public object Contents { get; set; }
public Action<T> Mutator { get; set; }
public abstract void Initialise();
}
... then:
public class A : BaseClass<A> {
public A() {
Mutator = Mutators.VariantA;
}
}
... as then you'd be writing something which can mutate "A" values. But in my experience this sort of generic nesting gets really messy, really quickly.
I've used your current example and changed the Method Signature of one of the classes to the following and it works
public abstract class BaseClass
{
public object contents { get; set; }
public Action<BaseClass> mutator;
public abstract void Initialise();
}
public static class Mutators
{
public static void VariantA(BaseClass baseClass)
{
// inputObj.contents = something else
}
public static void VariantB(A inputObj) { } // etc. etc.
}
public class A : BaseClass
{
public A()
{
mutator = Mutators.VariantA;
}
public override void Initialise()
{
/* set the value of contents property here */
}
}