Call any class sharing the same method name in C# - c#

I have a significant number of classes which share the same method name, but don not share a common base/interface. I cannot touch these classes, however, can I call the method irrespective of the defining class?
Eg:
Namespace n1: class A { void M1(n1.CustObj ob1){} }
Namespace n2: class B { void M1(n2.CustObj ob1){} }
Would it be possible to abstract from these common methods/parameters, like so?
method(Object obj)
{
obj.M1(new CustObj() {
x = 3;
}); // CustObj can either belong to n1 or n2
}

You have a number of classes, each of which has a method, with the same name, but with a different signature. The identical method names are a red herring here therefore as they are different methods.
This therefore rules out using dynamic or reflection to provide a single method that can handle all of them, unless you then hard-code tests for each type within the one method, or take Jonathan Wood's approach of passing in an existing instance of CustObj via a dynamic parameter too.
One solution might be to create extension methods for each type:
public void Method(this A obj)
{
obj.M1(new n1.CustObj()
{
x = 3
});
}
public void Method(this B obj)
{
obj.M1(new n2.CustObj()
{
x = 3
});
}
and so on. Then at least you can do someObj.Method(); on A, B and so forth.

You could use either the dynamic keyword or reflection.
Of the two, I prefer dynamic. However, since your constructor argument is also a different type you'd need to do something like this:
void method(dynamic obj, dynamic arg)
{
arg.x = 3;
obj.M1(arg);
}
I understand it's unlikely that your code is set up to do this but you haven't shown much of how your method is used. And in the end, this might be the best you can do if you're unable to modify the existing classes.

Related

Using methods from a type passed as a parameter in C#

I'm working in Q#, a quantum programming language based on C#. Quantum operations become C# classes, from which you can do things like
QuantumOperation.run(simulator, param1, param2);
which will use a quantum simulator simulator to run the operation QuantumOperation with the parameters param1 and param2.
I have many different operations which I want to run using different simulators and different parameters. What I would like to do is pass the quantum operation to another method, which will iterate through all the simulators and parameters. Then I can call this method with all the quantum operations I want.
The problem is that - as far as I can tell - a quantum operation is really a class and not an object. So, for example, if I write:
static void someMethod<Qop>(){...}
then I can call this with a quantum operation QuantumOperation as:
someMethod<QuantumOperation>()
and it compiles fine. However, if I try to do something like
static void someMethod<Qop>(Qop quantumOperation){ ...}
someMethod<QuantumOperation>(quantumOperation);
I get an error of "QuantumOperation is a type, which is not valid in the given context" for the second line.
If I try:
static void someMethod<Qop>(...){
...
Qop.Run(...);
...
}
it similarly says: "'Qop' is a type parameter, which is not valid in the given context".
What seems to be happening here is that I'm passing the class as a type. But then when I want to treat the type as a class, I can't. I looked for ways to pass a class as an argument, but I only see ways to do this that will create objects in that class. But I can't use an object, since "Run" is a static method.
(I could try passing an object and getting the class from that, but (a) I don't know if it's possible to create objects of quantum operation classes, and (b) I can only find public Type GetType, which returns a type and not a class, giving the same problem).
Is there any way to pass a class as an argument, then reference static methods of that class, without ever instantiating an object?
Now, maybe I'm asking too much, since, as far as C# is concerned, it's a coincidence that all these classes have a method called "Run". It maybe shouldn't be able to attempt to call methods with the same name from different classes.
Alternatively, I could construct a method for each quantum operation and then pass those methods. The method would look like:
static void QuantumOperationWrapper(QuantumSimulator simulator, Int int_parameter){
QuantumOperation.Run(simulator, in_parameter);
}
I would need to make a new method for each quantum operation, but that's not that bad. Then I can pass this as a delegate or Func to the methods I want. The problem is that the results I want are contained in the QuantumSimulator object. So what I want to do is something like:
QuantumOperationWrapper(simulator, 3);
simulator.GetResults();
But when I do this, the results are empty. My guess is that, somehow, the simulator is being passed by value, or treated as immutable, or something that prevents QuantumOperationWrapper from altering internal parameters of the simulator.
Is there any way to I can ensure that a delegate/Func will alter the internal state of its arguments?
EDIT: I can make a delegate for the Run method, as follows:
public delegate System.Threading.Tasks.Task<Microsoft.Quantum.Simulation.Core.QVoid> RunQop(QCTraceSimulator sim, long n);
Then I can construct static void someMethod(RunQop runner, ...), and pass QuantumOperation.Run as the first argument.
However, I have the same problem, that the QCTraceSimulator I pass as an argument does not keep any of the simulation results it makes when I call this.
So if I understand you correctly you want to execute a bunch of methods with parameters on different simulators. Here is how to do this:
We first off need a List of the operations we want to perform.
var methodList = new List<Func<QCTraceSimulator, long, Task<QVoid>>>
{
QuantumOperation.Run,
// Add more methods here
}
This is a List of Funcs. A Func is a delegate type that represents a method with a parameter and a return value. Here our methods need to look like this to be able to be added to our List:
public Task<QVoid> SomeName(QCTraceSimulator sim, long parameter)
{ ...}
We also need a list of parameters you want to try this with:
var paramsList = new List<long>
{
1,
2,
-2147483648,
2147483647
};
Now we can iterate through these and run our method like so:
public void RunMethodsOnSimulator(QCTraceSimulator sim)
{
// Iterate through every method
foreach (var method in methodList)
{
// Iterate through every parameter
foreach (var parameter in paramsList)
{
// Execute the given method with the given parameter
Task<QVoid> result = method(sim, parameter);
}
}
}
You can now do whatever you want with the result. This will result in every method being called with every parameter once
Please keep in mind that this answer only solves this problem for methods that return a Task<QVoid> and take a QCTraceSimulator and a long as parameter. This solution however avoids having to modify any QuantumOperation classes (and hopefully teaches you a little about delegates)
Here is what the paramsList and the RunMethodsOnSimulator method would like with 2 or more parameters:
methodList = new List<Func<QCTraceSimulator, long, int, Task<QVoid>>>
{
QuantumOperation.Run,
// Add more methods here
}
paramsList = new List<Tuple<long, int>>
{
new Tuple<long, int>(1, 1),
new Tuple<long, int>(2, 1),
new Tuple<long, int>(1, 2),
new Tuple<long, int>(-2147483648, 1)
}
public void RunMethodsOnSimulator(QCTraceSimulator sim)
{
// Iterate through every method
foreach (var method in methodList)
{
// Iterate through every parameter
foreach (var parameter in paramsList)
{
// Execute the given method with the given parameter
Task<QVoid> result = method(sim, parameter.Item1, parameter.Item2);
}
}
}
The way the Q# simulation tests deal with this is by having a method that receives a delegate with some code you want to execute on the simulator, in particular, the simulator unittests have the RunWithMultipleSimulators method that is broadly used in places like CoreTests.cs; this is an example of how it is used:
[Fact]
public void RandomOperation()
{
Helper.RunWithMultipleSimulators((s) =>
{
Circuits.RandomOperationTest.Run(s).Wait(); // Throws if it doesn't succeed
});
}
I think you're having two separate problems: you're not getting the results back, and dealing with classes is making looping through different operations difficult. Let me try to address them separately.
Results from running an operation are returned from the Run method, not stored in the simulator. More specifically, if you invoke an operation that returns a Q# int, the return value of the Run method will be Task<long>. You can then use the value property of the task to get the actual result, or use the async/await pattern, whichever you like.
All of the operation classes can be instantiated, and they all implement the ICallable interface. This interface has an Apply method that gets passed the arguments to the operation and returns the (asynchronous) results. Each instance has to get properly instantiated with a reference to the simulator; the easiest way to do this is to call the Get generic method on the simulator instance.
If you look at SimulatorBase.cs, in the implementation of the Run method on line 101, you can see how this is done. In this method, T is the class of the operation; I is the class of the operation input; and O is the class of the operation return value. You could use basically the same code to create a list of objects that you then call Apply on with varying arguments.
I did not understand everything but from the little that I understood you can use a non static wrapper and each wrapper allows accessing to a distinct Qop static class.
static public void TestQop()
{
someMethod(new Qop1(), 0, 0, 0);
someMethod(new Qop2(), 1, 1, 1);
}
static void someMethod<T>(T qop, int simulator, int param1, int param2)
where T : QopBase
{
qop.Run(simulator, param1, param2);
}
abstract class QopBase
{
public abstract void Run(int simulator, int param1, int param2);
}
class Qop1 : QopBase
{
public override void Run(int simulator, int param1, int param2)
{
QuantumOperation1.Run(simulator, param1, param2);
}
}
class Qop2 : QopBase
{
public override void Run(int simulator, int param1, int param2)
{
QuantumOperation2.Run(simulator, param1, param2);
}
}
Calling a method on an object whose type is generically defined requires you to use a generic constraint which ensures that the used generic type defines the expected method.
At its core, this relies on polymorphism to ensure that even though the specific type can vary, it is known that all usable generic types (which can be limited via constraints) contain this specific method you wish to call.
Static classes and methods lack this feature. They cannot inherit, nor can they implement interfaces, nor can you pass them via method parameters (and trying to do it via generic is not the solution). There is no way to create an "inheritance-like" link between two static methods of two different static classes; even if the methods have the same signature otherwise.
Are there other ways? Yes. In order of preferability:
(1) The straightforward and clean solution is avoiding statics and instead use instanced classes. If you are able to do this, this is the superior option.
(2) If you can't avoid statics, you can still wrap your static in an instanced wrapper, e.g.:
public class IWrapper
{
void DoTheThing(int foo);
}
public QuantumOperationWrapper : IWrapper
{
public void DoTheThing(int foo)
{
QuantumOperationWrapper.Run(foo);
}
}
public OtherStaticOperationWrapper : IWrapper
{
public void DoTheThing(int foo)
{
OtherStaticOperationWrapper.Run(foo);
}
}
This effectively "unstatics" the static code, in a way that you can now rely on the knowledge that all your wrappers implement/inherit the common BaseWrapper and thus both implement the DoTheThing method.
Your generic method can then rely on this:
public void DoTheGenericThing<T>(T obj) where T : IWrapper
{
obj.DoTheThing(123);
}
Note: In this particular case you don't even need generics to begin with. I assume you don't really need generics in this case, but since the answer can apply to both generic and non-generic cases, I've left the generic parameter in the solution. There may be specific cases in which you still need to use generics, though I suspect this is not one of them.
(3) A third but very dirty option is to use reflection to call the method anyway and just assume you never pass in a type which does not have the expected static method. But this is a really bad practice approach which will be fraught with bugs, it will be nigh impossible to debug, and it's absolutely not refactor-friendly.
Maybe you can try to deal with the situation using Interfaces. Something like that:
public interface IQuantumOperation
{
void Run();
void Run(MyFancyClazz simulator, MyFancyParam param1, MyFancyParam param2);
//And other possible methods
}
Then you can make use of this Interface as a type parameter's contract
static void someMethod<Qop>(Qop myQopParameter) where Qop : IQuantumOperation
{
...
//Now you can call your Run method
myQopParameter.Run(...);
...
//Or other fancy Run method with parameters like below
myQopParameter.Run(simulator, param1, param2);
}
Finally make sure that your QuantumOperation class implements the IQuantumOperation interface

Disambiguate between two constructors, when two type parameters are the same

Given
class Either<A, B> {
public Either(A x) {}
public Either(B x) {}
}
How to disambiguate between the two constructors when the two type parameters are the same?
For example, this line:
var e = new Either<string, string>("");
Fails with:
The call is ambiguous between the following methods or properties: 'Program.Either.Either(A)' and 'Program.Either.Either(B)'
I know if I had given the parameters different names (e.g. A a and B b instead of just x), I could use named parameters to disambiguate (e.g. new Either<string, string>(a: "")). But I'm interested in knowing how to solve this without changing the definition of Either.
Edit:
You can write a couple of smart constructors, but I'm interested in knowing if the Either's constructors can be called directly without ambiguity. (Or if there are other "tricks" besides this one).
static Either<A, B> Left<A, B>(A x) {
return new Either<A, B>(x);
}
static Either<A, B> Right<A, B>(B x) {
return new Either<A, B>(x);
}
var e1 = Left<string, string>("");
var e2 = Right<string, string>("");
How to disambiguate between the two constructors when the two type parameters are the same?
I'll start by not answering your question, and then finish it up with an actual answer that lets you work around this problem.
You don't have to because you should never get yourself into this position in the first place. It is a design error to create a generic type which can cause member signatures to be unified in this manner. Never write a class like that.
If you go back and read the original C# 2.0 specification you'll see that the original design was to have the compiler detect generic types in which it was in any way possible for this sort of problem to arise, and to make the class declaration illegal. This made it into the published specification, though that was an error; the design team realized that this rule was too strict because of scenarios like:
class C<T>
{
public C(T t) { ... }
public C(Stream s) { ... deserialize from the stream ... }
}
It would be bizarre to say that this class is illegal because you might say C<Stream> and then be unable to disambiguate the constructors. Instead, a rule was added to overload resolution which says that if there's a choice between (Stream) and (T where Stream is substituted for T) then the former wins.
Thus the rule that this kind of unification is illegal was scrapped and it is now allowed. However it is a very, very bad idea to make types that unify in this manner. The CLR handles it poorly in some cases, and it is confusing to the compiler and the developers alike. For example, would you care to guess at the output of this program?
using System;
public interface I1<U> {
void M(U i);
void M(int i);
}
public interface I2<U> {
void M(int i);
void M(U i);
}
public class C3: I1<int>, I2<int> {
void I1<int>.M(int i) {
Console.WriteLine("c3 explicit I1 " + i);
}
void I2<int>.M(int i) {
Console.WriteLine("c3 explicit I2 " + i);
}
public void M(int i) {
Console.WriteLine("c3 class " + i);
}
}
public class Test {
public static void Main() {
C3 c3 = new C3();
I1<int> i1_c3 = c3;
I2<int> i2_c3 = c3;
i1_c3.M(101);
i2_c3.M(102);
}
}
If you compile this with warnings turned on you will see the warning I added explaining why this is a really, really bad idea.
No, really: How to disambiguate between the two constructors when the two type parameters are the same?
Like this:
static Either<A, B> First<A, B>(A a) => new Either<A, B>(a);
static Either<A, B> Second<A, B>(B b) => new Either<A, B>(b);
...
var ess1 = First<string, string>("hello");
var ess2 = Second<string, string>("goodbye");
which is how the class should have been designed in the first place. The author of the Either class should have written
class Either<A, B>
{
private Either(A a) { ... }
private Either(B b) { ... }
public static Either<A, B> First(A a) => new Either<A, B>(a);
public static Either<A, B> Second(B b) => new Either<A, B>(b);
...
}
...
var ess = Either<string, string>.First("hello");
The only way I could think of would be to use reflection to iterate each constructor and then determine which one should be used based on the method body.
Of course this is way over the top and you should really just refactor your class, but it is a working solution.
It requires that you identify the byte[] for the method body that you want to use and 'hard code' that into the program (or read from file etc.). Of course you need to be very cautious that the method body may change over time, for example if the class is modified at any point.
// You need to set (or get from somewhere) this byte[] to match the constructor method body you want to use.
byte[] expectedMethodBody = new byte[] { 0 };
Either<string, string> result = null; // Will hold the result if we get a match, otherwise null.
Type t = typeof(Either<string, string>); // Get the type information.
// Loop each constructor and compare the method body.
// If we find a match, then we invoke the constructor and break the loop.
foreach (var c in t.GetConstructors())
{
var body = c.GetMethodBody();
if (body.GetILAsByteArray().SequenceEqual(expectedMethodBody))
{
result = (Either<string, string>)c.Invoke(new object[] { "123" });
break;
}
}
Disclaimer: Although I have tested this code briefly and it seems to work, I am really sceptical about how reliable it is. I do not know enough about the compiler to be comfortable in saying the method body wont change on a re-compile even if the code isn't changed. It may be that it would become more reliable if this class was defined in a pre-compiled DLL, again I don't know for sure though.
There may be other information you could get via reflection that might make it easier to identify the correct constructor. However, this was the first that came to mind and I haven't really looked into any other possible options at this time.
It would be much simpler if we could rely on the order of the constructors, but as quoted from MSDN, it is not reliable:
The GetConstructors method does not return constructors in a particular order, such as declaration order. Your code must not depend on the order in which constructors are returned, because that order varies.

Why is method overloading not working in this C# program?

namespace test
{
class Program
{
static void Main(string[] args)
{
Derived obj = new Derived();
int i = 10;
obj.Foo(i);
Console.ReadLine();
}
}
class Base
{
public virtual void Foo(int i)
{
Console.WriteLine("Base:Foo()");
}
}
class Derived:Base
{
public override void Foo(int i)
{
Console.WriteLine("Foo(int)");
}
public void Foo(object i)
{
Console.WriteLine("Foo(object)");
}
}
}
output of the program according to me should be Foo(int) but output is coming as Foo(object) please help me in understanding the diffrence in output
Good question, I can reproduce your results. If one takes a look at the C# specifications one will find the following snippets:
7.5.3 Overload resolution
For example, the set of candidates for a method invocation does not
include methods marked override (§7.4), and methods in a base class
are not candidates if any method in a derived class is applicable
(§7.6.5.1).
7.4 Member Lookup
Otherwise, the set consists of all accessible (§3.5) members named N
in T, including inherited members and the accessible members named N
in object. If T is a constructed type, the set of members is obtained
by substituting type arguments as described in §10.3.2. Members that
include an override modifier are excluded from the set.
7.6.5.1 Method invocations
The set of candidate methods is reduced to contain only methods from
the most derived types: For each method C.F in the set, where C is the
type in which the method F is declared, all methods declared in a base
type of C are removed from the set. Furthermore, if C is a class type
other than object, all methods declared in an interface type are
removed from the set.
Sounds a bit complicated? Even the C# designers seem to think so and put in the 'helpful' note:
7.6.5.1 Method invocations
The intuitive effect of the resolution rules described above is as
follows: To locate the particular method invoked by a method
invocation, start with the type indicated by the method invocation and
proceed up the inheritance chain until at least one applicable,
accessible, non-override method declaration is found. Then perform
type inference and overload resolution on the set of applicable,
accessible, non-override methods declared in that type and invoke the
method thus selected. If no method was found, try instead to process
the invocation as an extension method invocation.
If we take a look at your derived class, we see two possible methods for C# to use:
A) public override void Foo(int i)
B) public void Foo(object i)
Let's use that last checklist!
Applicability - Both A and B are applicable -(both are void, both are named 'Foo' and both can accept an integer value).
Accessibility - Both A and B are accessible (public)
Not Overridden - Only B is not overridden.
But wait you might say! A is more specific than B!
Correct, but that consideration is only made after we've disregarded option A. As Eric Lippert (one of the designers) puts it Closer is always better than farther away. (Thanks Anthony Pegram)
Addendum
There is always the 'new' keyword:
class Derived : Base
{
public new void Foo(int i)
{
Console.WriteLine("Foo(int)");
}
public void Foo(object i)
{
Console.WriteLine("Foo(object)");
}
}
Though the specifics of that best left for another question!
The simple datatype int descends from object. You are overriding the function and also overloading the parameter list. Since the function name is the same with a different signature the compiler allows this. For simple objects, I image one copy of the parameter signature in the most basic form is stored in the method table.

Is it possible to restrict the values of optional parameters in C#?

C# allows the use of optional parameters: one can specify the value in case the parameter is omitted in a call and the compiler then specifies the value itself.
Example:
public interface IFoo {
void SomeMethod (int para = 0);
}
This idea is useful but a problem is that one can define several "default values" on different levels of the class hierarchy. Example:
public class SubFoo : IFoo {
public void SomeMethod (int para = 1) {
//do something
}
}
If one later calls:
SubFoo sf = new SubFoo ();
sf.SomeMethod ();
Foo f = sf;
f.SomeMethod ();
The result is that the first call is done with para equal to 1 and the second with para equal to 0 (as interface). This make sense since the compiler adds the default values and in the first case the this is a SubFoo thus the default value is 1.
It is of course up to the programmer to maintain consistency, but such schizophrenic situations can easily occur when a programmer changes his/her mind in the middle of the process and forgets to modify all default values.
Problematic is that the compiler doesn't warn that different default values are in use whereas this can be checked by moving up the class hierarchy. Furthmore some people might mimic default parameters with:
public class SubFoo2 {
public virtual void SomeMethod () {
SomeMethod(1);
}
public void SomeMethod (int para) {
//do something
}
}
Which allows dynamic binding and thus overriding consistently. It thus requires one to be very careful with how default values are "implemented".
Are there ways to enforce (with compiler flags for instance) to check whether the default values are consistent? If not it would be nice to have at least a warning that something is not really consistent.
Well not necessary compile-time solution - but you can make unit test for that (I suspect that you're taking seriously unit testing and you run them frequently if you ask this kind of question). The idea is to create assertion method like AssertThatDefaultParametersAreEqual(Type forType) - find all classes that are not abstract (using reflection) and inherit from forType then iterate over all methods which have defined default parameters:
MethodInfo[] methodInfo = Type.GetType(classType).GetMethods(BindingFlags.OptionalParamBinding | BindingFlags.Invoke);
Group them by MethodInfo.Name and check does within the group all same parameters with default values (could be obtained by MethodInfo.GetParameters().Where(x => x.IsOptional)) have the equal property of ParameterInfo.DefaultValue.
edit: btw. that might not work in Mono because compilers aren't obligated to emit for instance: Optional BindingFlag.
If you want to have a compile time indication that a method is changing the default value of an optional argument, you're going to need to use some sort of 3rd party code analysis tool, as C# itself doesn't provide any means of providing such a restriction, or any warnings when its done.
As a workaround, one option is to avoid using optional parameter values and instead use multiple overloads. Since you have an interface here, that would mean using an extension method so that the implementation of the overload with a default value is still defined in the general case:
public interface IFoo
{
void SomeMethod(int para);
}
public static class FooExtensions
{
public static void SomeMethod(this IFoo foo)
{
foo.SomeMethod(0);
}
}
So while this approach does technically still allow someone to create an extension (or instance) method named SomeMethod and accepting no int argument, it would mean that someone would really need to go out of their way to actively change the "default value". It doesn't require implementations of the interface to supply the default value, which risks them unintentionally providing the wrong default value.
Define const int DefaultPara = 1; and then use that instead of hard coding numerical values.
interface IFoo
{
void SomeMethod (int para = DefaultPara);
}
public class SubFoo : IFoo {
public void SomeMethod (int para = DefaultPara) {
//do something
}
}

Pattern for calling method which takes the most derived form of the passed object

I was surprised when I ran into this situation and realized I wasn't sure what the best solution was.
Say I have the following three types:
class A { }
class B : A { }
class C : A { }
And the following three methods:
DoSomething(A a){ }
DoSomething(B b){ }
DoSomething(C c){ }
I have a List<A> which contains objects of type B and C
I would like to do this:
foreach(A a in list) { DoSomething(a) }
and have it call the method which matches most closely to the underlying type,
but of course this will always call DoSomething(A a)
I'd prefer not to have a bunch of type checking to get the right method call, and I don't want to add anything to the classes A, B or , C.
Is it possible?
This is a rather well-known issue with virtual dispatch in statically typed languages: it only handles one parameter (this) "virtually"; for all other parameters, the method call is bound using the static type of the argument. Since your list is a list of A, the code is only ever going to call the A overload.
You would need multiple dispatch to achieve the stated goal, and since the language does not provide this out of the box unless you switch to dynamic, so you will have to either make the switch or implement it yourself. There are many tradeoffs to consider when making this decision (and also when deciding how to implement multiple dispatch if needed), so don't do this lightly.
You'll pay a cost in performance, but one simple way of accomplishing this is by using the dynamic run-time binder. Simply cast the argument to dynamic:
foreach(A a in list) { DoSomething((dynamic)a); }
If you're willing to use dynamic keyword, I guess something like
DoSomething((dynamic)a);
will do the job for you.
Otherwise, with static types, you could say
void DoSomething(A a)
{
var aAsB = a as B;
if (aAsB != null)
DoSomething(aAsB);
var aAsC = a as C;
if (aAsC != null)
DoSomething(aAsC);
// general A case here
}
but that's maybe what you call a bunch of type checking.

Categories

Resources