I have 100 classes that will inherit 1 base class. Derived class can have A and B property, just A or B property, or don't have them at all. I need a pointer, from derived class to base class, that will trigger every time I call A or B property from derived classes.
class D1 : Base
{
int A { get; set; } // Point to Base A
}
class D2 : Base
{
int A { get; set; } // Point to Base A
int B { get; set; } // Point to Base B
}
class Base
{
int A => ExampleA();
int B => ExampleB();
int ExampleA()
{
return 10;
}
int ExampleB()
{
return 15;
}
}
static void Main(string[] args)
{
D1 d1 = new D1();
D2 d2 = new D2();
d1.A; //return 10
d2.A; //return 10
d2.B; //return 15
}
If You want to inherit not everything but sometimes A, sometimes B and only sometimes A and B then it looks like You should not inherit from the base class at all. Looks more like You should create 2 interfaces and for example:
class D1 : IBaseA
class D2 : IBaseA, IBaseB
You'll want to make the properties on the base class virtual, so then classes that inherit from it can optionally override the behaivour. (Or you could also make the methods ExampleA and ExampleB virtual and optionally override that behaivour instead), like so:
public class Base
{
// Made these properties get and set, instead of get (read) only
// default values are for illustration purposes
public virtual int A { get; set; } = 1;
public virtual int B { get; set; } = 1;
}
public class Foo : Base
{
public override int A { get; set; } = 10;
}
public class Bar : Base
{
public override int B { get; set; } = 10;
}
Let's test it:
var a = new Foo();
var b = new Bar();
Console.WriteLine($"a.A: {a.A}, a.B: {a.B}");
Console.WriteLine($"b.A: {b.A}, b.B: {b.B}");
If you don't specify anything, Foo and Bar will implicitly have A and B with the same visibility as A and B in the Base class. You can't change the visiblity of a member of a class "after the fact" (i.e without changing it in the base class), so if only some of your classes should expose A or B you'll want to follow what CherryQuery said in their answer
Actually in Base class you don't need A and B. Subclasses should then look like (assuming ExampleX methods are at least protected):
class D1 : Base
{
public int A => ExampleA(); // note this is get-only property
}
Related
I wonder if it is possible to force constraint on interface or abstract class generic type to be the same as the concrete class that implements it specially for it.
Lets say we want to check a fitness of certain entity to task and make it comparable to others in their proficiency
abstract class Entity
{
public abstract int Fitness(); //Bigger the number - more fit the entity is
public int MoreFitThan(Entity other)
{
return Fitness().CompareTo(other.Fitness());
}
}
class Fish : Entity
{
public int swimSpeed { get; set; }
public override int Fitness()
{
return swimSpeed;
}
}
class Human : Entity
{
public int testPoints { get; set; }
public override int Fitness()
{
return testPoints;
}
}
But now we can compare fish's speed with human's test passing capability, which doesn't make sense.
static void Main()
{
Human human = new Human() {testPoints = 10};
Fish fish = new Fish() { swimSpeed = 20 };
fish.MoreFitThan(human);
}
So is there a general way make some kind of class or interface that would force it's children classes to implement only own type to own type comparison?
Like so we could only compare people with people and fish to fish, but without explicitly specifying the type of comparable entity?
You can force the type being passed to MoreFitThan to match the inheriting class by using generics in the following way.
abstract class Entity<T> where T : Entity<T>
{
public abstract int Fitness(); //Bigger the number - more fit the entity is
public int MoreFitThan(T other)
{
return Fitness().CompareTo(other.Fitness());
}
}
class Fish : Entity<Fish>
{
public int swimSpeed { get; set; }
public override int Fitness()
{
return swimSpeed;
}
}
class Human : Entity<Human>
{
public int testPoints { get; set; }
public override int Fitness()
{
return testPoints;
}
}
Then the following would be a compilation error
Human human = new Human() {testPoints = 10};
Fish fish = new Fish() { swimSpeed = 20 };
fish.MoreFitThan(human);
because Human is not a Fish. However this would allow a class that inherits from Fish to be compared to a Fish.
class Trout : Fish
{
public int size { get; set; }
public override int Fitness()
{
return size;
}
}
The following works because a Trout is a Fish.
Trout trout = new Trout() {size = 10};
Fish fish = new Fish() { swimSpeed = 20 };
fish.MoreFitThan(trout);
My suggestion would be to create classes of comparable types, say: Swimmer, Runner, Learner that implement your interface, then in those classes also implement IComparable and enforce the constraint on that class type. Then you can extend those classes with Human for Learner, Fish for Swimmer, etc...
There are other ways to do it, but this should work fine for your needs.
Ok so, I've run into an interested and probably simple problem. I have a base class that is inherited by another class (child). I have the same parameterless constructor in the base and the child. I would like to set defaults in the child that propagate into the base properties. I would like to do something like this:
public partial class baseclass
{
public baseclass() {
//never called if instantiated from baseclass(string newp1)
p1 = "";
p2 = "google";
}
public baseclass(string newp1) {
p1 = newp1; //p2 will be "" and p1 will be newP1
}
public string p1 { get; set; }
public string p2 { get; set; }
}
public partial class childclass : baseclass
{
public childclass() {
//How can I call this to set some default values for the child?
p2 = "facebook";
}
public childclass(string newp1) : base(newp1) {
p1 = newp1; //p2 needs to be "facebook"
}
}
Use constructors chaining if you have duplicated code in several constructors:
public class baseclass
{
public baseclass() : this("google") { }
public baseclass(string newp1)
{
p1 = newp1; // the only place in your code where you init properties
p2 = "";
}
public string p1 { get; set; }
public string p2 { get; set; }
}
Child class should inherit baseClass
public class childclass : baseclass
{
public childclass() : this("facebook") { } // you can also call base here
public childclass(string newp1) : base(newp1) { }
}
Also keep in mind that parital just allows you split class/method definiton in several parts (e.g. keep it in different files). It is useful when you are generating classes (e.g. from database tables) but still want to add/customize something in generated classes. If you will put customized code directly into generated files, then it will be lost after classes re-generation. Read more
You can create a protected constructor in base class and call it in child class:
public class Base
{
public Base(int value1, int value2) { ... }
protected Base(string value1) { ... } // only for child class
}
public class Child : Base
{
public Child() : Base("Value") { ... }
}
Is there a way to copy an object fields to a base class in a derived class constructor without having to individually copying every field?
Example:
public class A
{
int prop1 { get; set; }
int prop2 { get; set; }
}
public class B : A
{
public B(A a)
{
//base = a; doesn't work.
base.prop1 = a.prop1;
base.prop2 = a.prop2;
}
}
A a = new A();
B b = new B(a);
public class A
{
public A(A a)
{
prop1 = a.prop1;
prop2 = a.prop2;
}
int prop1 { get; set; }
int prop2 { get; set; }
}
public class B : A
{
public B(A a) : base (a)
{
}
}
A a = new A();
B b = new B(a);
Something like this, although I'm not sure if it is syntactically correct because I didn't compile it. You should use the base keyword after the child class's constructor to pass the values of it's dependencies to the base class.
Edit: But I just realized that you are passing a base class to a child class. And this is a design flaw.
It sounds like you want to add all properties from A to B without having to specify them all separately. If you don't want to have to keep adding new ones to the constructor, you could use reflection to do the work for you.
public B(A a)
{
var bType = this.GetType();
// specify that we're only interested in public properties
var aProps = a.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
// iterate through all the public properties in A
foreach (var prop in aProps)
{
// for each A property, set the same B property to its value
bType.GetProperty(prop.Name).SetValue(this, prop.GetValue(a));
}
}
A few notes about this:
The above code sets public instance properties, so you'd need to change your properties in A to be public.
I'd only consider this safe because you know that B contains everything in A (since it is derived from it).
If you only have a few properties, especially if they don't change often, just list them individually... it'll be easier to see exactly what your code is doing.
I can't for the life of me understand why you want to do this
You are passing an instance of Base class into the constructor of a derived class. What are you trying to do?
have you tried this = a instead of base = a?
The members are private, so you can't access them from even a derived class. Even if they were protected, you still couldn't access them on an instance of A from the B class.
In order to do this without reflection, the members will have to be public:
public class A
{
public int prop1 { get; set; }
public int prop2 { get; set; }
}
// Define other methods and classes here
public class B : A
{
public B(A a)
{
//base = a; doesn't work.
base.prop1 = a.prop1;
base.prop2 = a.prop2;
}
}
If you really want to do this and cannot access the properties via inheritance then you can do via reflection like this:
public class Aclass
{
public int Prop1 { get; set; }
public int Prop2 { get; set; }
}
public class Bclass : Aclass
{
public Bclass(Aclass aInstance)
{
CopyPropertiesFromAltInstance(aInstance);
}
public void CopyPropertiesFromAltInstance(Aclass aInstance)
{
PropertyInfo[] aProperties = aInstance.GetType().GetProperties();
PropertyInfo[] myProperties = this.GetType().GetProperties();
foreach (PropertyInfo aProperty in aProperties)
{
foreach (PropertyInfo myProperty in myProperties)
{
if (myProperty.Name == aProperty.Name && myProperty.PropertyType == aProperty.PropertyType)
{
myProperty.SetValue(this, aProperty.GetValue(aInstance));
}
}
}
}
}
Is it possible in C# to bind two objects of different classes but with similar properties?
For Example:
class Program
{
static void Main(string[] args)
{
test t = new test();
test2 t2 = new test2();
}
}
public class test
{
public int Number { get; set; }
}
public class test2
{
public int Number { get; set; }
}
So is it possible to say t = t2 somewhow?
You can have both classes implement an interface, if you don't care about what implementation of the interface is used.
For example:
class Program
{
static void Main(string[] args)
{
INumber t = new test();
INumber t2 = new test2();
}
}
public class test : INumber
{
public int Number { get; set; }
}
public class test2 : INumber
{
public int Number { get; set; }
}
public interface INumber
{
int Number { get; set; }
}
An interface is a sort of contract, that provides a definition of what properties and methods an implementing class must define. You can read more on interfaces here.
When your classes implement a shared interface, you're able to to implicitly convert one type into another type, such as in the example above.
Without the addition of extra code, no, you cannot do that.
Even though they are "similar" they are regarded as totally different types by the compiler, and cannot be assigned to each other.
Now, you can include an implicit operator on one (or both) in order to allow implicit casting between the two.
public class test
{
public static implicit operator test(test2 t)
{
return new test(tt.Number);
}
public static implicit operator test2(test t)
{
return new test2(t.Number);
}
public int Number { get; set; }
}
But that is as close as you can get to supporting that syntax.
I have two classes A and B and I want to cast an instance of A to B. What's the best way?
How Can I make a utility class to perform this task?
public class A
{}
public class B
{}
A good place to start is by reviewing the MSDN documentation on Casting and Type Conversions.
As there's no direct relationship between the two classes, you'll need to write a Conversion Operator. For example:
public class A
{
public int AValue { get; set; }
}
public class B
{
public int BValue { get; set; }
public static explicit operator B(A instanceOfA)
{
return new B { BValue = instanceOfA.AValue };
}
}
You could then write:
A instanceOfA = new A { AValue = 7 };
B instanceOfB = (B)instanceOfA;
// Will output "7"
Console.WriteLine(instanceOfB.BValue);
The documentation I've derived this example from is on MSDN, Using Conversion Operators.
If there was a direct relationship between the two classes, for example B derives from A, for example:
public class A
{
public int Value { get; set; }
}
public class B : A
{
public string OtherValueSpecificToB { get; set; }
}
You wouldn't then need any extra code if you wanted to cast from B to A:
B instanceOfB = new B { OtherValueSpecificToB = "b", Value = 3 };
A instanceOfBCastToA = (A)instanceOfB;
// Will output "3";
Console.WriteLine(instanceOfBCastToA.Value);
// Will not compile as when being treated as an "A" there is no "OtherValueSpecificToB" property
Console.WriteLine(instanceOfBCastToA.OtherValueSpecificToB);