Unity3d, C# pass function as parameter - c#

I have ScriptA with a lot of void functions:
void methodOne() {
some code
}
void methodTwo(int a, int b) {
}
I want to pass to static method of another script. Lets say it scriptB:
ScriptB.staticMethod(methodOne, some, other, primitive, parameters);
ScriptB.staticMethod(methodTwo(a, b), some, other, parameters);
The main Idea of my scripts is that ScriptB will get datas from server and call methods that got from ScriptA to make changes in my game depending on data.

I am not sure what you are trying to achieve here.
But to answer your question, you can pass methods as parameters using delegates. Here is an example:
public class ScriptA
{
public delegate void MethodOneDelegate(int a, int b);
public void MethodOne(int a, int b)
{
Console.WriteLine(a + b);
}
}
public static class ScriptB
{
public static void StaticMethod(ScriptA.MethodOneDelegate function, int a, int b)
{
function(a, b);
}
}
public static void Main()
{
ScriptA scriptA = new ScriptA();
ScriptB.StaticMethod(scriptA.MethodOne, 1, 2);
}
There is alternative solutions, you can take a look at System.Func and System.Action.

Do you need to start the methods when you put them as parameters? Or do you need the values from those methods?
Either way, you could do two things, either try this or just pass the name of the method as string and in your method check which name has been entered and start that method in your method.

Related

how to allow access to method to only be passed as a delegate but not executed?

I have a private method I would like to allow access to only to be passed as a delegate but not be executed otherwise.
for example:
class a
{
public delegate int myDelegate(int a);
public static int myMethod(int data, myDelegate action)
{
//my code
}
private static int methodA(int a){ //code}
private static int methodb(int a){ //code}
}
class b
{
public void anotherMethod()
{
var doAction = new myDelegate(methodA);
result = myMethod(8, doAction);
}
}
so in my example I would like methodA and MethodB to only be executed from within class a, but still enabling access to them so they can be used as delegates to be passed to methods from class a.
is it at all possible?
currently I am getting an error "methodA is inaccessible due to protection level"
What you are saying is not possible. Once a class has an instance of a delegate, no one can stop it from calling it. So if class B were able to pass a delegate to myMethod, it would also be able to call that delegate directly, unless methodA and methodB need special parameters, that only A knows about, to do anything useful.
One way of doing something similar is to create an enum called something like MethodOfA and declare MethodA and MethodB as the possible values of the enum. In class A declare a private Dictionary<MethodOfA, MyDelegate> methodDict that records what each enum value correspond to. Then declare another overload of myMethod that takes a MethodOfA like this:
public static int myMethod(int data, MethodOfA action)
=> myMethod(data, methodDict[action]);
Nevertheless, this looks like bad design to me. Maybe you don't need the overload of myMethod(int, MyDelegate) in the first place, and just check the enum to perform the corresponding action. The other thing that you might try is the strategy pattern.
If I'm understanding you correctly, you'd like to know how to use delegates (pass actions / functions) as parameters?
If so, then you should use Action<> and/or Func<> as they're delegates. Your code could look like this then:
class a
{
public int myMethod(int data, Func<int, int> func)
{
return func.Invoke(data);
}
}
class b
{
public void anotherMethod()
{
var classA = new a();
var result = classA.myMethod(8, Double);
}
private int Double(int i)
{
return i * 2;
}
}

Call Method based on Type of Parameter

I have an object that can be of type AudioRequest or VideoRequest. Both classes inherit from Request. I have this class:
public static DoThings
{
public static void HandleRequest(AudioRequest r)
{
// Do things.
}
public static void HandleRequest(VideoRequest r)
{
// Do things.
}
}
I want to be able to call DoThings.HandleRequest(r) where r can be either a VideoRequest or AudioRequest and have it call the correct one. Is that possible? I have no control over the *Request classes, so I can't do anything to them. I do have control of the DoThings class and the code that calls HandleRequest. This is the code that calls it, it is WebAPI:
public Response Post(Request input)
{
return DoThings.HandleRequest(input);
}
The code above gives the error Argument 1: cannot convert from 'Request' to 'AudioRequest'.
The original code that I was cleaning up had this:
if (input.GetType() == typeof(AudioRequest))
{
var audioRequest = (AudioRequest)input;
DoThings.HandleRequest(audioRequest);
}
else if (input.GetType() == typeof(VideoRequest))
{
var videoRequest = (VideoRequest)input;
DoThings.HandleRequest(videoRequest);
}
But I figured there was a cleaner way to do this.
Based on the information you've provided so far, your question appears to be a duplicate of How to call a function dynamically based on an object type. I agree with the answer, that the fact that you want to do this suggests you should rethink the design. But, you can use dynamic to accomplish what you want.
Here's a simple console program that demonstrates the basic idea:
class Program
{
static void Main(string[] args)
{
A b = new B(), c = new C();
M(b);
M(c);
}
static void M(A a)
{
WriteLine("M(A)");
M((dynamic)a);
}
static void M(B b)
{
WriteLine("M(B)");
}
static void M(C c)
{
WriteLine("M(C)");
}
}
class A { }
class B : A { }
class C : A { }
The output is:
M(A)
M(B)
M(A)
M(C)
As you can see, in each case the M(A) method is called first, and then the appropriate M(B) or M(C) overload is called from M(A).
In your own example, this could look something like this:
public static DoThings
{
public static void HandleRequest(Request r)
{
// Dynamic dispatch to actual method:
HandleRequest((dynamic)r);
}
public static void HandleRequest(AudioRequest r)
{
// Do things.
}
public static void HandleRequest(VideoRequest r)
{
// Do things.
}
}
Note that dynamic does incur a run-time cost, particularly the first time a method is called with a given run-time type. But depending on the frequency and complexity of these "requests", using dynamic could be the cleanest way out of the current situation.
C# will call the appropriate function that matches the arguments and their types.
That being said, both of your functions accept AudioRequest, I believe one of those should accept a VideoRequest.
public static DoThings
{
public static void HandleRequest(AudioRequest r)
{
// Do things.
}
public static void HandleRequest(VideoRequest r)
{
// Do things.
}
}
If for some reason you must have two different functions that take only AudioRequest you can differentiate between two function with an extra parameter
public static class DoThings
{
public static void HandleRequest(AudioRequest r)
{
// Do things.
}
public static void HandleRequest(AudioRequest r, bool UseAlternativeMethod)
{
// Do other things.
}
}
Simply having a second parameter will call the second method regardless of it's value.
This isn't a best practices solution as you'd rather discriminate between them by accurately renaming the method name to be accurate but in practice you don't always have a choice.

params parameter and normal parameters

using System;
using System.Collections.Generic;
namespace Generics
{
class Minivan
{
public void foo(int z, int x)
{
Console.WriteLine("foo with two parameters");
}
public void foo(params int[] z)
{
Console.WriteLine("foo with two params parameter");
}
}
class D
{
public static void Main()
{
Minivan car3 = new Minivan();
car3.foo(10,20); // which method will be called here!!!
}
}
}
which foo method is called? and why?
in a simple sentence "more specific is better than less specific"
so public void foo(int z, int x) will be called.
it is because of method overload resolution rules in C#.
you can read more in this answer
Compiler will choose a method with explicit parameters (as said in c# spec). But if you'll call method with 3 params the params implementation'll be called
To put it simply, the one with the two explicit parameters is chosen here.
I don't claim to know the reasoning behind that decision in the spec, but I would image it goes something like "You went to the trouble to explicitly handle the case where two parameters are passed in, so that would be the only sensible choice of method to choose"
this is a simple overload, when you explicitly call the function with two parameters it will call public void foo(int z, int x)

Do I need to update references?

I updated a library project method,
public static void EatFruit(string a, string b)
to
public static void EatFruit(string a, string b, bool IsEatFruit = false)
Now there are hundred of projects using this library, Do I need to update references of library dll in all projects and solutions ?
I updated the server and they all are failing by this error,
Method not found void EatFruit(System.String, System.String)'.
Do I need to update references of library dll in all projects and solutions ?
Yes. C# is a statically typed language and you've changed the method signature. You might try a slightly different refactoring approach here and just add the new functionality instead of replacing existing functionality:
public static void EatFruit(string a, string b)
{
// change the BODY of the existing method,
// but not its SIGNATURE.
EatFruit(a, b, false);
}
public static void EatFruit(string a, string b, bool IsEatFruit)
{
// move the BODY of the existing method here.
// this is a NEW method unknown to existing clients.
}
With this approach you wouldn't need to update existing clients because they can still call the same method with the same signature. New clients will also be able to call the new method, though.
Yes you need to update it there.
There is a possible solution by just making the new method overload and forcing the old one to call it.
Just do the following:
public static void EatFruit(string a, string b)
{
EatFruit(a,b,false);
}
public static void EatFruit(string a, string b, bool IsEatFruit = false)
If old projects don't need IsEatFruit parameter simply use two functions in your library project:
public static void EatFruit(string a, string b)
public static void EatFruit(string a, string b, bool IsEatFruit = false)
Even if is an optional param you will have to update the references, if you don't want to do it just create the new method.
public static void EatFruit(string a, string b)
{
}
public static void EatFruit(string a, string b, bool IsEatFruit = false)
{
}
http://en.wikipedia.org/wiki/Polymorphism_(computer_science)

C# overload methods behavior with interface [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C# 4: conflicting overloaded methods with optional parameters
I just have one small research and created next code.
namespace Test {
class Program
{
public interface ITestA
{
void MethodA(int a, int b);
}
public class TestAClass : ITestA
{
public void MethodA(int a, int b)
{
Console.WriteLine("MethodA with param");
}
public void MethodA(int a, int b, bool logic = true)
{
Console.WriteLine("MethodA logic with param");
}
}
public interface ITestB
{
void MethodA(int a, int b, bool logic = true);
}
public class TestBClass : ITestB
{
public void MethodA(int a, int b)
{
Console.WriteLine("MethodB with param");
}
public void MethodA(int a, int b, bool logic = true)
{
Console.WriteLine("MethodB logic with param");
}
}
static void Main(string[] args)
{
var testA = new TestAClass();
testA.MethodA(1, 1);
var testB = new TestBClass();
testB.MethodA(1, 1);
}
} }
I have a question why compiler always choose short method with 2 parameters. And of course all this work by the same way and without Interface.
Thanks
This boils down to how the compiler treats named and optional parameters.
Check out this article at MSDN for more information, especially the paragraph Overload Resolution.
If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.
This is why in your case the compiler chooses the method without any optional parameters.
Because compiler finds a method that correspond perfectly to calling method and use that.
Compiler searches for other suitable methods if first way fails...

Categories

Resources