Considering the classes below, I would like to be able to write:
B b = new B();
b.f(1); // calls b._a.f(int)
b.f("howdy!"); // calls b._a.f(string)
Class A cannot be modified.
public class A
{
public void f(int i) { }
public void f(string s) { }
}
public class B
{
public void f<T>(T v)
{
_a.f(v); // fails
}
A _a = new A();
}
If you really want to simplify your f pass-through down to a single method, you'll have to use run-time type checking. I don't see any other way around it. Generics aren't going to work here.
public void f(object v)
{
if (v is int i)
_a.f(i);
else if (v is string s)
_a.f(s);
else
throw new InvalidOperationException();
}
I gather that you are hesitant to just expose _a because there are some methods on it that you would rather not be accessible to the caller? Could you introduce an interface, or would that be considered a modification to class A?
public interface IFoo
{
void f(int i);
void f(string s);
}
public class A : IFoo
{
...
}
public class B
{
public IFoo A => _a;
}
Related
https://dotnetfiddle.net/CZYmsC
using System;
public interface IMyInterface
{
}
public class MyObject : IMyInterface
{
}
public class Program
{
public static void Main()
{
// returns null
Console.WriteLine(TupleWithInterface((true, new MyObject())));
// returns IMyInterface
Console.WriteLine(TupleWithClass((true, new MyObject())));
Console.WriteLine(Interface(new MyObject()));
Console.WriteLine(Class(new MyObject()));
}
public static IMyInterface TupleWithInterface<T>(T gen)
{
if (gen is ValueTuple<bool, IMyInterface> a)
{
return a.Item2;
}
return null;
}
public static IMyInterface TupleWithClass<T>(T gen)
{
if (gen is ValueTuple<bool, MyObject> b)
{
return b.Item2;
}
return null;
}
public static IMyInterface Interface<T>(T gen)
{
if (gen is IMyInterface c)
{
return c;
}
return null;
}
public static IMyInterface Class<T>(T gen)
{
if (gen is MyObject d)
{
return d;
}
return null;
}
}
In my scenario I need to check to see if T is a tuple<,> that contains IMyInterface and if so extract it. I don't need to worry about anything other than a Tuple of 2. The code above doesn't work the way I was hoping, though really I need to do something even more complicated like this:
if (gen is ValueTuple<object, IMyInterface> || gen is ValueTuple<IMyInterface, object>)
Is something like this even possible? I'm currently handling the scenario where T is IMyInterface with code similar to above but I have no idea how to handle when T is a Tuple.
I would suggest just adding an overload for tuples:
public static IMyInterface TupleWithInterface<T, T1>((T,T1) gen)
{
if (gen.Item2 is IMyInterface a)
{
return a;
}
return null;
}
I have an abstract class A and a abstract method with a parameter which is again abstract class B defined in the same abstract class A. When I extended this abstract class A as apart of another class C how can I implement the method with parameter of nested abstract class.
public abstract class A<T, V>
{
public abstract int GetObject(T t, V v);
public abstract int GetAnotherObject(B b);
public abstract class B{}
}
This class is extended by another class C
public class C: A<ABC, DEF>
{
public C()
{
}
public override int GetObject(ABC abc, DEF def)
{
return 10;
}
public override int GetAnotherObject(B b)
{
return 15;
}
}
How to implement class B with some properties and pass in GetAnotherObject method. Could someone please help me.
From ECMA:
Any class nested inside a generic
class declaration or a generic struct
declaration (ยง25.2) is itself a
generic class declaration, since type
parameters for the containing type
shall be supplied to create a
constructed type.
So, you cannot implement nested B without providing type arguments for A.
void Main()
{
var c = new C();
var result = c.GetAnotherObject(new BImpl<string, int>());
}
public class BImpl<T, V> : A<T, V>.B
{
public override int BM()
{
return 1;
}
}
// Or you can supply type arguments right here
//public class BImpl : A<string, int>.B
//{
// public override int BM()
// {
// return 1;
// }
//}
public abstract class A<T, V>
{
public abstract int GetObject(T t, V v);
public abstract int GetAnotherObject(B b);
public abstract class B
{
public abstract int BM();
}
}
public class C : A<string, int>
{
public C()
{
}
public override int GetObject(string abc, int def)
{
return 10;
}
public override int GetAnotherObject(B b)
{
return b.BM();
}
}
You're very close already.
public class C<ABC, DEF> : A<ABC, DEF>
{
public C()
{
}
public override int GetObject(ABC abc, DEF def)
{
return 10;
}
// since B is a nested class of A, it has no scope outside of A
// outside of the definition of A, it must always be referred to as A.B
public override int GetAnotherObject(A<ABC,DEF>.B b)
{
return 15;
}
}
public class D : A<ABC,DEF>.B
{
// implementation of A.B
}
Keep in mind that C will always take exactly A.B. You will never be able to define an implementation of A.B (let's call it D) and have C's method signature refer to that in the override. GetAnotherObject is defined in A as taking an A.B and must therefore be implemented to accept any A.B, not some specific implementation of A.B.
RE: your comment on how to implement A.B inside C
There is no point to implementing A.B inside C. C will still have to have A.B in its method signature. But if you really must, for some reason.
public class C<ABC, DEF> : A<ABC, DEF>
{
// C's implementation of A
public override int GetAnotherObject(A<ABC,DEF>.B b)
{
return 15;
}
public class D : A<ABC,DEF>.B
{
// implementation of A.B
}
}
Note that GetAnotherObject still takes an A.B, not a D.
How about
public class C<ABC, DEF> : A<ABC, DEF>
{
public C()
{
}
public override int GetObject(ABC abc, DEF def)
{
return 10;
}
public override int GetAnotherObject(B b)
{
return 15;
}
}
Just postfix the class with the generics.
I have a delegate expecting parameters of type A as parameters. So A is the base class. Class B and C inherit from A.
The problem is that although B and C inherit from the base class A, the DoSomething functions at the bottom of the script can't be converted to the delegate.
public class A { }
public class B : A { }
public class C : A { }
public delegate void CallbackAction(params A[] paremeters);
public class Main
{
public int main(params string[] args)
{
CallbackAction callbackAction;
callbackAction = DoSomething1;
callbackAction = DoSomething2;
callbackAction = DoSomething3;
return 0;
}
public void DoSomething1(A arg0) { }
public void DoSomething2(B arg0) { }
public void DoSomething3(C arg0) { }
}
Is there any way to use params in a delegate and be able to use classes that have the params class as their base class?
When compiling the error I get is:
Error 5 No overload for 'DoSomething3' matches delegate 'SKConsole.CallbackAction'
I'm using .NET 4 and XNA
EDIT::
Ok let me explain why I am using this I am creating a console. This means a programmer using my console can add a command (console.AddCommand("help", Help) to the console, Help here is a function. When you are ingame and typing help in the console it will execute the function Help().
I now want it to work with console.AddCommand("setSpeed", SetPlayerSpeed) aswell. The SetPlayerSpeed function has 1 parameter, an int. But I want it to work with any function so if a programmer creates the function DoSomeFancyStuff(float a, string b, int c) I want the console to create a command and if you type in the correct string in the console execute these command.
I already tried making lots of delegates for different functions, but this is kinda ugly in my opinion.
What I then tried was the following
public abstract class SKConsoleParameter
{
protected string value;
public SKConsoleParameter(string value)
{
this.value = value;
}
public string GetRawValue()
{
return value;
}
public abstract bool IsValid();
public abstract object GetValue();
}
public class StringParam : SKConsoleParameter
{
public StringParam(string value) : base(value) { }
public override bool IsValid()
{
return true;
}
public override object GetValue()
{
return value;
}
}
public class IntParam : SKConsoleParameter
{
public IntParam(string value) : base(value) { }
public override bool IsValid()
{
int i;
return int.TryParse(value, out i);
}
public override object GetValue()
{
int i;
if (int.TryParse(value, out i))
return i;
else
return 0;
}
}
Was this does is that if a developer creates a function like:
DoSomethingCool(StringParam s, IntParam i)
Then it can receive the values by using (string)s.GetValue() and (int)i.GetValue()
The StringParam and IntParam classes both inherit from SKConsoleParameter, so i though I could now create the follwoing delegate
void CoolDelegate(params SKConsoleParameter[] parameters)
But this doesn't work.. Because of the abstract problem with class A, B and C at the top of this page
Does anyone have any ideas to counter this problem?
You are looking for the error in the wrong place. C# allows contravariance in delegates' input parameters. The problem with your code is that your delegate takes params A[], while your method takes a single A. This is not allowed. Delcare your delegate as accepting a single A:
delegate void Callback1 (B a) ;
void Test11 (A a) {}
void Test12 (B b) {}
Callback1 c11 = Test11 ; // OK
Callback1 c12 = Test12 ; // OK
Note also that this does not work with array parameters:
delegate void Callback2 (B[] a) ;
void Test21 (A[] a) {}
void Test22 (B[] b) {}
Callback2 c21 = Test21 ; // compile error
Callback2 c22 = Test22 ; // OK
based on your updated code -- try this. As long as your method matches the delegate the contravariance should work as expected in .NET 3.5 or better
public abstract class SKConsoleParameter
{
protected string value;
public SKConsoleParameter(string value)
{
this.value = value;
}
public string GetRawValue()
{
return value;
}
public abstract bool IsValid();
public abstract object GetValue();
}
public class StringParam : SKConsoleParameter
{
public StringParam(string value) : base(value) { }
public override bool IsValid()
{
return true;
}
public override object GetValue()
{
return value;
}
}
public class IntParam : SKConsoleParameter
{
public IntParam(string value) : base(value) { }
public override bool IsValid()
{
int i;
return int.TryParse(value, out i);
}
public override object GetValue()
{
int i;
if (int.TryParse(value, out i))
return i;
else
return 0;
}
}
class Program
{
public delegate void CoolDelegate(params SKConsoleParameter[] parameters);
static void Main(string[] args)
{
var s = new StringParam("Glenn");
var i = new IntParam("12");
var coolDel = new CoolDelegate(DoSomethingCool);
coolDel(s, i);
}
public static void DoSomethingCool(params SKConsoleParameter[] parameters)
{
if (parameters == null) throw new ArgumentNullException("parameters");
foreach (var item in parameters)
{
if (item is IntParam)
{
// do something interesting
continue;
}
if (item is StringParam)
{
// do something else interesting
continue;
}
throw new NotImplementedException("unknown param type");
}
}
}
Try this code:
public class A { }
public class B : A { }
public class C : A { }
public static class Helper
{
public static Action<A> DoSomething;
}
class Program
{
static void Main(string[] args)
{
var a = new A();
var b = new B();
var c = new C();
Helper.DoSomething = new Action<A>(DoSomething1);
Helper.DoSomething = (Action<A>)new Action<B>(DoSomething2);
Helper.DoSomething = (Action<A>)new Action<C>(DoSomething3);
}
public static void DoSomething1(A a) { }
public static void DoSomething2(B a) { }
public static void DoSomething3(C a) { }
}
I've got a class, which has three overloaded methods. Let's say, there is:
class MyChildClass
{
public void myMethod(int i)
{ /* do something with i */ }
public void myMethod(int a, string b)
{ /* get i from a and b and call: */ myMethod(i); }
public void myMethod(string c, string d)
{ /* get i from c and d and call: */ myMethod(i); }
}
Now I'd like this class to be a private field in other (parent) class, but I need those three methods to be accessible. For now, I just did:
class MyBaseClass
{
private MyChildClass myObject = new myChildClass(); // or similar
public void myMethod(int i)
{ myObject.myMethod(i); }
public void myMethod(int a, string b)
{ myObject.myMethod(a, b); }
public void myMethod(string c, string s)
{ myObject.myMethod(c, d); }
}
Is there a way to implement it as one short method? Something which would look like:
public void myMethod(unknownListOfArgumentsOfDifferentTypes args)
{ myObject.myMethod(args); }
I tried to use public void myMethod(params object[] something) but it didn't work. Is it possible, or do I have to "project" every method into another?
EDIT: Child class has various methods and fields, which I want to be accessible for parent class only. That's why I don't want parent to derive after it. I didn't explain that, sorry if it looked like child class contains only those three methods. Those are the methods I want to be accessible as public methods of parent class.
Why don't you do
class MyChildClass : MyBaseClass
{
}
same effect, less code, and this way MyChildClass is a MyBaseClass
If you implement some sort of generic facade using reflection you'll just be reducing performance, bypassing the benefits of type safety and delaying the discovery of problems.
You'll also have have a "has a" relationship instead "is a" relationship which is incongruent with your class names.
If you want to give up this simplicty with its associated benefits you could make use the GetMethodBySig extension accepted in this post.
Something like this,
class SemiGenericFacade<T> where T : new()
{
private readonly t = new T();
public void CallVoidOnT(string name, params object[] parameters)
{
var paramTypes = parameters.Select(p => typeof(p))
var match = typeof(T).GetMethodBySig(typeof(void), paramTypes)
.Single(mi => mi.Name == name);
match.Invoke(this.t, parameters);
}
}
Following on from Piotr Justyna's comment, implementing and using this method results in the cat turning into a tiger and eating her kittens.
If you were to do this it would make sense to add to the linked extension
public static class Extensions
{
public static MethodInfo GetMethodByNameThenSig(
this Type type,
string name,
Type returnType,
params Type[] parameterTypes)
{
return type.GetMethods().Where((m) =>
{
if (m.Name != name)
{
return false;
}
if (m.ReturnType != returnType)
{
return false;
}
var parameters = m.GetParameters();
if ((parameterTypes == null || parameterTypes.Length == 0))
{
return parameters.Length == 0;
}
if (parameters.Length != parameterTypes.Length)
{
return false;
}
for (int i = 0; i < parameterTypes.Length; i++)
{
if (parameters[i].ParameterType != parameterTypes[i])
{
return false;
}
}
return true;
}).Single();
}
}
Which you could use like this,
class GenericFacade<T> where T : new()
{
private readonly t = new T();
public void CallOnInternal(string name, params object[] parameters)
{
var paramTypes = parameters.Select(p => typeof(p))
var match = typeof(T).GetMethodByNameThenSig(
name,
typeof(void),
paramTypes);
match.Invoke(this.t, parameters);
}
public TResult CallOnInternal<TResult>(string name, params object[] parameters)
{
var paramTypes = parameters.Select(p => typeof(p))
var match = typeof(T).GetMethodByNameThenSig(
name,
typeof(TResult),
paramTypes);
return (TResult)match.Invoke(this.t, parameters);
}
}
FINAL EDIT
Looking at the code involved to use reflection and considering the cost associated with the loss of type safety. I'd suggest its better to establish the "has-a" relationship explicitly in the traditional manner.
You can use public void myMethod(params object[] something) as in:
public static void Main()
{
UnknownArgumentsMethod1(1, 2, 3, "foo");
}
public static void UnknownArgumentsMethod1(params object[] list)
{
UnknownArgumentsMethod2(list);
}
public static void UnknownArgumentsMethod2(params object[] list)
{
foreach (object o in list)
{
if (o.GetType() == typeof(int))
{
Console.WriteLine("This is an integer: " + (int)o);
}
else if (o.GetType() == typeof(string))
{
Console.WriteLine("This is a string: " + (string)o);
}
}
}
The obvious answer would be to have inheritance.
In your case (even though the names of the classes suggest otherwise) the way to do it is by inheriting the ChildClass in the BaseClass and that way you would have the methods from the ChildClass exposed through the BaseClass.
ex:
class MyBaseClass: MyChildClass
{
}
If the classes are not related and you just want to have an instance of MyChildClass in MyBaseClass but only expose a certain set of methods but by not making the others private what you could do is expose the MyChildClass instance through an interface that only exposes the necessary fields like so:
public class BaseClass
{
public IChildClass ChildClassInstance = new ChildClass();
}
public class ChildClass : IChildClass
{
public void myMethod(int i)
{ /* do something with i */ }
public void myMethod(int a, string b)
{ /* get i from a and b and call: */ myMethod(i); }
public void myMethod(string c, string d)
{ /* get i from c and d and call: */ myMethod(i); }
}
public interface IChildClass
{
void myMethod(int i);
void myMethod(int a, string b);
}
and then you could access only the methods that you allow to be exposed through an instance of the base class:
BaseClass test = new BaseClass();
test.ChildClassInstance.myMethod(1);
test.ChildClassInstance.myMethod(1,"test");
I realise this has been asked before, but I didn't find a clear agreement on the best solution.
Is using dynamic (like below) the best way to do this?
I guess its best to avoid dynamic whenever possible to help catch problems at compile-time.
(classA1 and classA2 implement Interface A and likewise for B)
public static void Foo(InterfaceA a, InterfaceB b)
{
Foo((dynamic)a, (dynamic)b);
}
static void Foo(classA1 a, classB1 b) { //some code }
static void Foo(classA2 a, classB2 b) { //some code }
static void Foo(classA1 a, classB2 b) { //some code }
static void Foo(classA2 a, classB1 b) { //some code }
Or similarly...
public static void Foo(InterfaceA a, InterfaceB b)
{
((dynamic) a).Foo(b);
}
public classA1
{
void Foo(classB1 b) { //some code }
}
//repeated for other cases
Is using dynamic (like below) the best way to do this?
Well it's a way to do it - so long as the execution-time types will always end up with something that overload resolution will be happy with.
You might want to put a backstop method of
static void Foo(object x, object y)
in case none of the methods are applicable (e.g. a is a non-ClassA1/ClassA2 implementation). It's not going to help you if both values are null, mind you...
I would usually attempt to redesign so that this isn't required, but it's hard to know the best solution without more context.
Are 'classA1' and so on implementations of InterfaceA? If so then why not just declare the Foo functions as accepting InterfaceA and InterfaceB and cast them within to the concrete implementation expected by the function? E.g.,
static void Foo(InterfaceA a, InterfaceB b) {
classA1 c1 = a as classA1;
classB1 b1 = b as classB1;
// ... etc
}
Dynamic isn't intended to be used this way.
You could do something AWFUL with reflection - but I'm sure it's not better than doing dynamic:
void Main()
{
var a = "hello";//5;
var b = "hello";
var type1 = a.GetType();
var type2 = b.GetType();
var t = typeof(FooClass);
var methods = t.GetMethods();
foreach(var method in methods)
{
var parameters = method.GetParameters();
if(parameters.Length == 2)
{
if(parameters[0].ParameterType == type1
&& parameters[1].ParameterType == type2)
{
method.Invoke(this, new object[]{ a, b });
}
}
}
}
public static class FooClass
{
public static void Foo(int i, string s)
{
"Foo1".Dump();
}
public static void Foo(string s, string s2)
{
"Foo2".Dump();
}
}
C# has traditionally been a statically-typed language. The dynamic keyword adds dynamic typing to the language. The usual advice is to use "dynamic" sparingly. Here may be a case where you need it.
Generics won't cut it as this won't compile:
private void button1_Click(object sender, EventArgs e)
{
Foo(new classA1(), new classB2());
}
static void Foo<T, T1>(T a, T1 b) where T: InterfaceA
where T1: InterfaceB
{
Foo2(a, b);
}
static void Foo2(classA1 a, classB1 b) { }
static void Foo2(classA2 a, classB2 b) { }
static void Foo2(classA1 a, classB2 b) { }
static void Foo2(classA2 a, classB1 b) { }
interface InterfaceA { }
interface InterfaceB { }
class classA1 : InterfaceA { }
class classA2 : InterfaceA { }
class classB1 : InterfaceB { }
class classB2 : InterfaceB { }