I have a lot of classes that store different types of data but manipulate the data differently. Is there someway I can abstract what class I'm using...and just call the class's methods? I will have one object that I'm using at a given moment, masterclass.
For example I have class1 and class2. Both classes can do .add .subtract...etc.
I want to say...masterclass is now class1. So I can do masterclass.add instead of class1.add. Then change masterclass to class2 and do a masterclass.subtract instead of class1.subtract.
Ok...maybe this is clearer:
class cat
{
String legs="4 legs";
String claws="cat has lots of claws";
public string GetLegs()
{ return legs+claws;
}
}
class bird
{
String legs="2 wings";
String talons="Bird has 2 talons";
public string GetLegs()
{ return legs+talons;
}
}
class animal;
mainfunction()
{
string temp;
animal = cat;
temp = animal.GetLegs();
animal = bird;
temp = animal.getLegs();
}
You could do it in several ways, either you use interfaces, and implement it like for example:
public interface ICalculate {
void Add();
void Subtract();
}
and implement your classes in such a way that they inherit from the interface, like so:
public class SpecificClass : ICalculate {
public void Add() {
// ...
}
public void Subtract() {
// ...
}
}
public class OtherSpecificClass : ICalculate {
public void Add() {
// ...
}
public void Subtract() {
// ...
}
}
or you can use an abstract base class like:
public abstract class AbstractCalculate {
public abstract void Add();
public abstract void Subtract();
}
and implement specific classes like:
public class SpecificCalculate : AbstractCalculate {
public override void Add() {
// ...
}
public override void Subtract() {
// ...
}
}
in the first example you can create your specific classes like:
ICalculate calc1 = new SpecificCalculate();
and call
calc1.Add();
in the second one one, you can use
AbstractCalculate calc11 = new SpecificCalculate();
and call
calc1.Add();
both have a similar way of working, both have their advantages
more info you can find for example on MSDN
Per suggestion of Ed Plunkett, you could have then for example following implementations (lets say for the ICalculate version)
IList<ICalculate> calculations = new List<ICalculate>();
// <-- add specific instances to the list
calculations.Add( new SpecificClass() );
calculations.Add( new OtherSpecificClass() );
// iterate the list
foreach (var calculation in calculations) {
calculation.Add();
}
or to be more specific to your updated question
public interface IAnimal {
int GetLegs();
}
public class Bird : IAnimal {
public int GetLegs() {
return 2;
}
}
public class Cat : IAnimal {
public int GetLegs() {
return 4;
}
}
and the program would use it like
class Program {
static int GetLegs(IAnimal animal) {
return animal.GetLegs();
}
static void Main(string[] args) {
Cat cat = new Cat();
Bird bird = new Bird();
Console.WriteLine( GetLegs( bird ) ); // 2
Console.WriteLine( GetLegs( cat ) ); // 4
}
}
Or like
IList<IAnimal> animals = new List<IAnimal>();
animals.Add( new Cat() );
animals.Add( new Bird() );
int totalLegs = 0;
foreach (var animal in animals) {
totalLegs += animal.GetLegs(); // or totalLegs += GetLegs( animal );
}
Console.WriteLine( totalLegs ); // 6
I'm having an hierarchy that looks smth like:
public class SomeBaseClass { }
public class Child1: SomeBaseClass { }
public class Child2: SomeBaseClass { }
//Objects hierarchy
public class A
{
public A(B b, SomeBaseClass sbc) { }
}
public class B
{
public B(C c) { }
}
public class C
{
public B(C c, SomeBaseClass sbc) { }
}
...
public class X
{
public X(SomeBaseClass sbc) { }
}
class Program
{
static void Main()
{
var builder = new ContainerBuilder();
builder.RegisterInstance(new Child1()).As<SomeBaseClass>();
var container = builder.Build();
container.Resolve<A>();
//Some work here.
}
}
At some point of time I would like to use Child2 instead of Child1 instance and use it in all hierarchy dependencies. Is there a way to do this without building new Container? It would be perfect to have something like:
public A ResolveWithBinding(IComponentContext cc, SomeBaseClass sbc)
{
return cc.Resolve<A>().WithRegistered<SomeBaseClass>(sbc);
}
UPD: I've found some sort of workaround:
//Registration code
var factory = new SomeBaseClassAncFactory();
builder.Register(() => factory.GetCurrentInstance()).As<SomeBaseClass>();
//Resolve code
public SomeBaseClass GetCurrentInstance()
{
if(StaticClass.SomeProperty=="A")
return new Clild1();
return new Clild2();
}
And I'm afraid that it is not really thread-safe way. And it seems like using static properties is not a "best practice". I hope, there's another solution.
Implement a proxy class that allows you to switch dynamically between Client1 and Client2. For instance:
public class SomeBaseClassProxy : SomeBaseClass
{
private Client1 c1;
private Client2 c2;
public SomeBaseClassProxy(Client1 c1, Client2 c2) {
this.c1 = c1;
this.c2 = c2;
}
private GetClient() {
return StaticClass.SomeProperty == "A" ? c1 : c2;
}
// SomeBaseClass methods
public override void SomeMethod() {
GetClient().SomeMethod();
}
}
I am struggling to cast in a tree hierarchy structure below is an example of the class hierarchy structure I would really appreciate if someone can point me in the right direction.
I am unable to cast
var myobj2 = (IR<JB>)JR;
Classes:
public class BASEA{ }
public class B: BASEA{ }
public class C: B{ }
public interface IR<T> { }
public abstract class JR<T> : IR<T> where T : B
{ public abstract void SetRule(); }
public class Action: JB<C>
{
public override void SetRule()
{
//Logic
}
}
public static class RuleLib
{
public static void ApplyTest<T>(T obj, IR<T> JB) where T:B
{
var myobj2 = (IR<JB>)JR; //=> does not cast!
}
}
public class Test
{
[Test]
public void demo()
{
var obj = new B();
var action = new Action();
RuleLib.ApplyRule(obj,action);
}
}
For this to work, your IRule interface needs to be covariant. The example given here shows the following covariance:
IEnumerable<Derived> d = new List<Derived>();
IEnumerable<Base> b = d;
This is basically exactly what you're doing. So in your code all you need to do is write
public interface IRule<out T> { ... }
instead of
public interface IRule<T> { ... }
This makes it so that you can cast from an IRule<U> to IRule<V> where U is a subclass of V (e.g. casting from IRule<ShiftAction> to IRule<Job>).
This is what I want to do in C# (within class Helper - without generic arguments),
List<AbstractClass<dynamic>> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add((AbstractClass<dynamic>) thing);
}
This helper class would take and work with AbstractClass<> objects and give back AbstractClass<> of specific generic type. AbstractClass<T> contains many functions which return T / take in T like public T Invoke().
For Helper class T cannot be known beforehand. The Add<T>(.. thing) function is not in a class of type T.
To be used like this in Helper class's functions,
foreach(var c in data.Where(x => ...))
{
// public T Invoke() { ... } function within AbstractClass<T>
var b = c.Invoke();
// logic
}
This also fails,
List<AbstractClass<object>> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add((AbstractClass<object>) thing);
}
Now I think I can have,
List<dynamic> data; // or List<object> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add(thing);
}
but I want the constraint that List named data has only elements of type like
ConcreteClass : AbstractClass<OtherClass>
So we would know that there is an public T Invoke() function but we do not know what it returns. This is helpful to avoid mistakes of say misspelling Invocke and only knowing at run-time.
I want to avoid casting to dynamic every time to invoke functions that give back generic type T
To do what you want to do you are going to need to use a Contravariant interface
public class Program
{
static void Main()
{
var m = new Helper();
m.Add(new ConcreteClass());
m.Process();
}
class Helper
{
List<IAbstractClass<OtherClassBase>> data = new List<IAbstractClass<OtherClassBase>>();
public void Add(IAbstractClass<OtherClassBase> thing)
{
this.data.Add(thing);
}
public void Process()
{
foreach(var c in data.Where(x => x.ShouldBeProcessed()))
{
var b = c.Invoke();
Console.WriteLine(b.Question);
var castData = b as OtherClass;
if (castData != null)
Console.WriteLine(castData.Answer);
}
}
}
public interface IAbstractClass<out T>
{
bool ShouldBeProcessed();
T Invoke();
}
abstract class AbstractClass<T> : IAbstractClass<T>
{
public bool ShouldBeProcessed()
{
return true;
}
public abstract T Invoke();
}
class ConcreteClass : AbstractClass<OtherClass>
{
public override OtherClass Invoke()
{
return new OtherClass();
}
}
class OtherClassBase
{
public string Question { get { return "What is the answer to life, universe, and everything?"; } }
}
class OtherClass : OtherClassBase
{
public int Answer { get { return 42; } }
}
}
You do not need to tell Add what kind of class you are passing it, all that matters is it derives from the type specified. You could do public void Add(IAbstractClass<object> thing) and every class would work, but Invoke() would only return objects inside the foreach loop.
You need to figure out what is the most derived class you want Invoke() to return and that is what you set as the type in the list.
Maybe this will work for you:
public class Program
{
static void Main()
{
var m1 = new Helper<OtherClass>();
m1.Add(new ConcreteClass());
var m2 = new Helper<int>();
m2.Add(new ConcreteClass2());
}
class Helper<T>
{
List<AbstractClass<T>> data = new List<AbstractClass<T>>();
public void Add<T1>(T1 thing) where T1 : AbstractClass<T>
{
this.data.Add(thing);
}
}
class AbstractClass<T> { }
class OtherClass { }
class ConcreteClass : AbstractClass<OtherClass> { }
class ConcreteClass2 : AbstractClass<int> { }
}
I'm having a small design issue and wanted to consult.
Lets say we have the following class hierarchy:
abstract class A
{
}
class B : A
{
}
class C: A
{
}
I want that both B and C have a certain field x so that it's value is different between the classes but shared among all instances of the same class (i.e: if b1, b2 are instances of B and c1,c2 instances of C then b1.x = b2.x and c1.x = c2.x and b1.x != c1.x).
Is there an elegant way to do this by taking advantage of the fact that both B, C derive from the same base class or do I have to create a static field x in both classes?
Thanks in advance.
You mean like this?
abstract class A
{
static Dictionary<Type, int> all_x;
protected int X {
get { return all_x[GetType()]; }
set { all_x[GetType()] = value; }
}
}
If it has to be a field so you can pass by reference:
abstract class A
{
class SharedType { int x; }
static Dictionary<Type, SharedType> all_shared;
protected SharedType Shared {
get
{
Type t = GetType();
SharedType result;
if (!all_shared.TryGetValue(t, out result) {
result = new SharedType();
all_shared.Add(t, result);
}
return result;
}
}
}
Also, we can improve performance by doing the lookup only once per instance:
abstract class A
{
class SharedType { int x; }
static Dictionary<Type, SharedType> all_shared;
protected SharedType Shared;
A() {
Type t = GetType();
if (!all_shared.TryGetValue(t, out Shared) {
Shared = new SharedType();
all_shared.Add(t, Shared);
}
}
}
What should those values be for the field x? If you need to specify that the value of x for A should be "a", the value of x for B should be "b" etc., then you will have to specify the values "a", "b", ... somewhere and then you mught as well just use:
abstract class A {
public static int x = 1; // Just using "int" as example.
}
class B : A {
public static int x = 2;
}
If you do not care what the values are (which type do you need then) but merely want the values to be "different", then instead of using fields you could use something like:
abstract class A {
public int X { get { return this.GetType().GetHashCode(); } }
}
This does not take hash collisions into account, but maybe it is useful anyway?
What is it you are trying to achieve?
To build on Ben Voigt's first answer, I think what you want for your base class is this:
public abstract class A
{
private static ConcurrentDictionary<Type, int> _typeIDs = new ConcurrentDictionary<Type, int>();
private static int _nextID = 1;
public int TypeID
{
get
{
return _typeIDs.GetOrAdd(this.GetType(), type => System.Threading.Interlocked.Increment(ref _nextID));
}
}
}
public abstract class A
{
public abstract int Value { get; }
}
public class B : A
{
public override int Value { get { return 1; } }
}
public class C : A
{
public override int Value { get { return 2; } }
}
The only way I know to do this is if you make class A a generic class, i.e. class A<T>. Then have class B implement a different type for the generic type than the generic type that Class C implements.
If you don't use generics, then I believe this is impossible in .NET.
Here is an example where lets say the value you were interested in was a data structure with members int Foo and string Bar. One derive class could implement the an identical structure (but different derived type) than the other - the two structures would implement the same interface.
interface IAvalue
{
int Foo { get; set;}
string Bar {get; set;}
}
struct BValue
: IAvalue
{
public int Foo { get; set; }
public string Bar { get; set; }
}
struct CValue
: IAvalue
{
public int Foo { get; set; }
public string Bar { get; set; }
}
abstract class A<T> where T : IAvalue
{
protected static T myValue;
}
class B : A<BValue>
{
static B()
{
myValue.Foo = 1;
myValue.Bar = "text1";
}
}
class C : A<CValue>
{
static C()
{
myValue.Foo = 2;
myValue.Bar = "text2";
}
}
You can use one .net feature: If you have static data members in a generic class, .net creates different instances of static data members for each generic type you use.
So, you can write:
public abstract class A<T> where T : A<T>
{
protected static int myVariable { get; set; }
}
And inherit your classes as:
public class B : A<B>
{
public B()
{
myVariable = 1;
}
public int GetVariable()
{
return myVariable;
}
}
public class C : A<C>
{
public C()
{
myVariable = 2;
}
public int GetVariable()
{
return myVariable;
}
}
Then every instance of B will have shared access to one instance of myVariable and every instance of C will have shared access to another.
So, if you add Set(int a) method:
public void Set(int a)
{
myVariable = a;
}
And run the following code:
static void Main(string[] args)
{
B b1 = new B();
C c1 = new C();
B b2 = new B();
C c2 = new C();
Console.Write("{0}; ", b1.GetVariable()); // 1
Console.Write("{0}; ", b2.GetVariable()); // 1
Console.Write("{0}; ", c1.GetVariable()); // 2
Console.Write("{0}; ", c2.GetVariable()); // 2
Console.WriteLine();
c2.Set(333);
Console.Write("{0}; ", b1.GetVariable()); // 1
Console.Write("{0}; ", b2.GetVariable()); // 1
Console.Write("{0}; ", c1.GetVariable()); // 333
Console.Write("{0}; ", c2.GetVariable()); // 333
Console.ReadLine();
}
You get: 1; 1; 2; 2;
1; 1; 333; 333; output.
I would suggest defining a static Dictionary<Type, Integer[]>, and having the base-class constructor call GetType() on itself and see if it's yet in the static dictionary. If not, create a new single-element array and store it in the dictionary. Otherwise grab the array from the dictionary and store it in an instance field. Then define a property which reads or writes element zero of the array. This approach will achieve the requested semantics for all derivatives and sub-derivatives of the class.