Super type with flexible functionality - c#

How can I implement this:
I have 3 types (actually Interface): A , B and C
A has no methods, but B and C have some methods.
I want the type A in some situations can be cast to type B and use B methods and in other situation cast to type C and use its methods?

class Program
{
interface A { }
interface B :A { void b(); } // B inherits from A
interface C :A { void c(); } // C also inherits from A
static void Main()
{
// declare vars
A a = null;
B b = null;
C c = null;
// a can happily hold references for B.
a = b;
// To call B's methods you need to cast it to B.
((B)a).b();
// a can happily hold references for C.
a = c;
// To call C's methods you need to cast it to C.
a = c;
((C)a).c();
}
}
From your comments
class Program
{
private interface A { }
private interface B : A { string b();}
private interface C : A { string c();}
class BClass : B { public string b() { return "B"; } }
class CClass : C { public string c() { return "C"; } }
private static void Main()
{
A a = null;
B b = new BClass();
C c = new CClass();
a = b;
((B)a).b();
a = c;
((C)a).c();
}
}

Related

How to get all inherited classes

Let's imagine that we have a class called A, and this class is inherited from class B, and also class B inherited from class C. We can extend this sequence as long as we want. How can we get all classes from this sequence? Like:
A
B
C
...
Try this code:
Type type = typeof(C);
while (type.BaseType!=null)
{
type = type.BaseType;
Console.WriteLine(type.Name);
}
// C
// B
// A
// Object
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
foreach (Type type in assembly.GetTypes())
{
if (typeof(A).IsAssignableFrom(type))
Console.WriteLine(type);
}
// These can be in various projects / assemblies
class A { }
class B : A { }
class C : A { }
class D : B { }
class E { }
class F : E { }
class G : D { }
Prints:
A
B
C
D
G

Set multiple base classes

I have a problem. I am using my MainActivity.cs as a FragmentActivity now, but I also need it to be a AppCompatActivity. Now when I try this:
public class MainActivity : FragmentActivity, AppCompatActivity
It gives the error:
Class 'MainActivity' cannot have multiple base classes:
'FragmentActivity' and 'AppCompatActivity'
But I need both, so how can I fix this?
C# does not support multiple base classes, but allows to implement multiple interfaces. And composition is legal too.
Do it like this:
class A
{
public void DoAStuff() { }
}
class B
{
public void DoBStuff() { }
}
class C
{
private readonly A a;
private readonly B b;
public C(A a, B b) => (this.a, this.b) = (a, b);
public void DoAStuff() => a.DoAStuff();
public void DoBStuff() => b.DoBStuff();
public static implicit operator A(C c) => c.a;
public static implicit operator B(C c) => c.b;
}
Note, you will be able to cast C to A and B implicitly like
C c = new C(new A(), new B());
c.DoAStuff();
c.DoBStuff();
A a = c;
a.DoAStuff();
B b = c;
b.DoBStuff();
but
new[] { new C(new A(), new B()) }.Cast<B>().ToArray()
will throw System.InvalidCastException.
Use
new[] { new C(new A(), new B()) }.Select(i => (B)i).ToArray();
If FragmentActivity and AppCompatActivity implement interfaces do it like this:
interface IA
{
void DoAStuff();
}
class A : IA
{
public void DoAStuff() { }
}
interface IB
{
void DoBStuff();
}
class B : IB
{
public void DoBStuff() { }
}
class C : IA, IB
{
private readonly IA a;
private readonly IB b;
public C(IA a, IB b) => (this.a, this.b) = (a, b);
public void DoAStuff() => a.DoAStuff();
public void DoBStuff() => b.DoBStuff();
}
In this case any casting will work fine.

Modify class variable returned by method

I'm starting to learn C# and I'm stuck with a little problem. I don't know if there's a solution for what I want to do or I have to do it in a different way.
Anyway, I'm trying to modify the value of a class variable returned by a method.
The code below shows more or less what I want to do.
public Class AClass
{
private SomeClass A;
private SomeClass B;
private SomeClass C;
private SomeClass D;
private enum SomeEnum {A, B, C, D};
private void SomeMethod(SomeEnum theEnum, SomeClass theNewValue){
SomeClass oldValue = GetSomeClass(theEnum);
oldValue = theNewValue;
}
private SomeClass GetSomeClass (SomeEnum theEnum){
switch(theEnum){
case A:
return A;
case B:
return B;
case C:
return C;
case D:
return D;
}
return null;
}
}
Do you guys have any solution or alternative?
You are almost there. You just need to directly overwrite A, B, C or D:
public Class AClass
{
private SomeClass A;
private SomeClass B;
private SomeClass C;
private SomeClass D;
private enum SomeEnum {A, B, C, D};
public void UpdateInstance (SomeEnum theEnum, SomeClass newClass)
{
switch(theEnum)
{
case SomeEnum.A:
A = newClass;
break;
case SomeEnum.B:
B = newClass;
break;
case SomeEnum.C:
C = newClass;
break;
case SomeEnum.D:
D = newClass;
break;
}
}
}
The switch statement is ugly though and can only grow as the complexity of the code does. Better to replace it with a dictionary of functions:
private readonly Dictionary<SomeEnum, Action<SomeClass>> instanceUpdaters =
new Dictionary<SomeEnum, Action<SomeClass>>
{
{ SomeEnum.A, x => A = x },
{ SomeEnum.B, x => B = x },
{ SomeEnum.C, x => C = x },
{ SomeEnum.D, x => D = x }
};
public void UpdateInstance (SomeEnum theEnum, SomeClass newClass)
{
instanceUpdaters[theEnum](newClass);
}
public interface ISomeClass
{
/// <summary>
/// eample class method
/// </summary>
/// <returns></returns>
string doSomething();
}
public class SomeClassA : ISomeClass
{
public string doSomething()
{
return "A";
}
}
public class SomeClassB : ISomeClass
{
public string doSomething()
{
return "B";
}
}
public class SomeClassC : ISomeClass
{
public string doSomething()
{
return "C";
}
}
public class SomeClassD : ISomeClass
{
public string doSomething()
{
return "D";
}
}
public class Class1
{
private SomeClassA A;
private SomeClassB B;
private SomeClassC C;
private SomeClassD D;
private enum SomeEnum { A, B, C, D };
private void SomeMethod(SomeEnum theEnum, ISomeClass theNewValue)
{
ISomeClass oldValue = GetSomeClass(theEnum);
oldValue = theNewValue;
}
private ISomeClass GetSomeClass(SomeEnum theEnum)
{
switch (theEnum)
{
case SomeEnum.A:
return A;
case SomeEnum.B:
return B;
case SomeEnum.C:
return C;
case SomeEnum.D:
return D;
}
return null;
}
}
Also you can use dynamic class creation for not using switch.
One possible ways is to go with reflection:
private SomeClass GetSomeClass(SomeEnum theEnum)
{
return (SomeClass)GetType().GetField(theEnum.ToString(), BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this);
}

Create dynamic struct with Generic Type

I'm new in .net and C# and I'm trying to create an instance of MyStruct, without known the Type before.
so my class receive 3 type in the constructor and I need to create an Instance of MyStruct with this type.
I looked on internet and saw the last part but I can't compile this.
namespace IQUnionTag
{
public class IQUnionTag
{
private struct MyStruct<A, B, C>
{
public A value1;
public B value2;
public C value3;
}
private object MyStructure;
private Type a;
private Type b;
private Type c;
public IQUnionTag(Type a, Type b, Type c)
{
this.a = a;
this.b = b;
this.c = c;
int d = 2;
var d1 = typeof (MyStruct<>); // Doesn't compile
Type[] typeArgs = { a, b, c };
var makeme = d1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(makeme);
Console.WriteLine(o);
}
}
}
I just want something like
Mystructure = new MyStruct<a,b,c> // this doesn't compile too
typeof(MyStruct<>) make error compile like
Erreur Using the generic type 'IQUnionTag.IQUnionTag.MyStruct<A,B,C>' requires 3 type arguments
i certainly missed something, can you help me to create my instance?
It is not clear what is your purpose but you can do:
public class IQUnionTag
{
private struct MyStruct<A, B, C>
{
public A value1;
public B value2;
public C value3;
}
private object MyStructure;
private Type a;
private Type b;
private Type c;
public IQUnionTag(Type a, Type b, Type c)
{
this.a = a;
this.b = b;
this.c = c;
int d = 2;
var d1 = typeof(MyStruct<,,>); // this is the way to get type of MyStruct
Type[] typeArgs = { a, b, c };
var makeme = d1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(makeme);
Console.WriteLine(o);
}
}

Parameter of OfType<????> when used in a method with C#

I have this code to get "A" as a filtered result.
public static void RunSnippet()
{
Base xbase = new Base();
A a = new A();
B b = new B();
IEnumerable<Base> list = new List<Base>() { xbase, a, b };
Base f = list.OfType<A>().FirstOrDefault();
Console.WriteLine(f);
}
I need to use IEnumerable<Base> list = new List<Base>() {xbase, a, b}; from a function as follows:
public static Base Method(IEnumerable<Base> list, Base b (????)) // I'm not sure I need Base b parameter for this?
{
Base f = list.OfType<????>().FirstOrDefault();
return f;
}
public static void RunSnippet()
{
Base xbase = new Base();
A a = new A();
B b = new B();
IEnumerable<Base> list = new List<Base>() { xbase, a, b };
//Base f = list.OfType<A>().FirstOrDefault();
Base f = Method(list);
Console.WriteLine(f);
}
What parameter do I use in '????' to get the same result from the original code?
It seems like you are looking for a generic way to do what is in Method based on different children types of Base. You can do that with:
public static Base Method<T>(IEnumerable<Base> b) where T: Base
{
Base f = list.OfType<T>().FirstOrDefault();
return f;
}
This will return the first instance from b that is of type T (which has to be a child of Base).
If you want to query on a type, you can try something like this:
public static Base Method(IEnumerable<Base> list, Type typeToFind)
{
Base f = (from l in list
where l.GetType()== typeToFind
select l).FirstOrDefault();
return f;
}
If it's not what you are searching for, please clarify.

Categories