This question already has answers here:
How to call an appropriate method by string value from collection?
(3 answers)
Closed 3 years ago.
I have 1000 methods called method0001, method0002 , ... ,method1000.
I have a variable that takes values between 1 and 1000.
If the value of the variable is x, I'd like to call methodx. For instance, if the value of the variable is 34, I'd like to call method0034. How can I code this in C# please?
Many people are asking what is need for Methodwxyz. Every method is a different type of math question.
i've done this, following the helpful comments but am getting errors (edited the question from earlier)
using System.Collections.Generic;
using UnityEngine;
public class TextControl : MonoBehaviour
{
public static TextControl instance;
void Start()
{
instance = this;
}
// Update is called once per frame
void Update()
{
this.GetType().GetMethod("Template00" + "1").Invoke(this, null);
}
public static string Templates001()
{
// doing something here
}
}
thanks
You could do this through reflection. Edit for a quick sample (forgot invoke parameters). Some tips about reflection:
If you get a nullexception that means it can't find the method
The method you are invoking needs to be public
If you use obfuscation you may not have the same names for the method
Code
public class Program
{
public static void Main(string[] args)
{
Check method1 = new Check(1);
Check method2 = new Check(2);
}
}
public class Check
{
public Check(int x)
{
this.GetType().GetMethod("Method" + x).Invoke(this, null);
}
public void Method1()
{
Console.WriteLine("Method 1");
}
public void Method2()
{
Console.WriteLine("Method 2");
}
}
Related
This question already has answers here:
Pass Method as Parameter using C#
(13 answers)
Closed 3 years ago.
(I'm a bit new to programming so if this doesn't make sense just say so)
Let's say that a method takes in a void as parameter. Ex:
method(anotherMethod);
and I want to write the void inside of the brackets rather than writing the void and putting the name inside so rather than
void theVoid() {
doSomethingHere;
}
and then calling it like
method(theVoid());
I wanted to do
method({ doSomethingHere; })
directly, is it possible to do so?
The thing you are trying to do is called "lambda" it's anonymous functions
Here is the documentation for that.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions
Your method will need to be passed a Delegate (if you do not return anything, an Action should be fine)
https://learn.microsoft.com/en-us/dotnet/api/system.action-1?view=netcore-2.2
Method(TheVoid()); // does not compile
Method(TheVoid); // compiles
using System;
public class Example
{
public void Method(Action func)
{
func();
}
public void TheVoid()
{
Console.WriteLine("In example.TheVoid");
}
}
public class Program
{
public static void TheVoid()
{
Console.WriteLine("In TheVoid");
}
public static void Main()
{
var example = new Example();
example.Method(example.TheVoid);
example.Method(() => {
Console.WriteLine("In lambda");
});
example.Method(TheVoid);
}
}
Example of what you are trying to do
I want to use a dependency that I downloaded in the class scope. This code works:
using System;
using System.IO;
using System.Collections;
namespace PrintFilesToConsole
{
class Preprogram
{
public void Main2()
{
IEnumerable myDirs = System.IO.Directory.EnumerateDirectories("/Users/Eunice/Desktop");
Console.WriteLine("Hello World!");
}
}
class Program
{
static void Main(string[] args)
{
Preprogram preprogram = new Preprogram();
preprogram.Main2();
}
}
}
but when I write
System.IO.Directory.EnumerateDirectories
("/Users/Eunice/Desktop");
outside of the function called
Main2
, into the scope of the class
Preprogram
, the computer says that the function doesn't exist in the current context
unless I assign the return value to a variable, as in
IEnumerable myDirs = System.IO.Directory.EnumerateDirectories("/Users/Eunice/Desktop");
enter code here
Let's simplify your example to demonstrate where the problem lies.
We have the class A which contains the method DoSomething.
public class A
{
public int DoSomething()
{
return 42;
}
}
lets say it also contains the method MakeStuff, which calls the DoStuff method:
public class A
{
public int DoSomething()
{
return 42;
}
public void MakeStuff()
{
int x = this.DoSomething();
// We called the method DoSomething, which returns 42, and now x equals 42.
}
}
what we did in MakeStuff is we called a method and assigned the return value to a local variable.
We could also put a field (or property) in the class A:
public class A
{
private int y;
...
}
and we can even assign a default value to that field:
public class A
{
private int y = 10;
...
}
but the value doesn't have to be hardcoded: we can also use the return value of a function, just as we did in the MakeStuff method when we assigned the return value to a local variable:
public class A
{
private int y = this.DoSomething();
// Now y equals 42, because DoSomething() returns 42.
...
}
but we cannot call a function outside of a method if we discard the return value, e.g. we cannot do this:
public class A
{
this.DoSomething();
// This will not compile!
}
I hope this simple example shows why you get the described error. I tried to keep it as simple as possible - yet if you don't understand parts of the answer or anything, please feel free to comment where you need help with and I will do my best to help you.
This question already has answers here:
Why use the 'ref' keyword when passing an object?
(10 answers)
Closed 7 years ago.
the following code does not work as I would expect:
using System;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyClass cl = new MyClass();
cl.doSomething();
}
}
public class MyClass : BaseClass
{
protected override void doSelect(DataTable dt)
{
dt = null;
}
public void doSomething()
{
base.Fill();
}
}
public class BaseClass
{
private DataTable dtMain = null;
protected virtual void doSelect(DataTable dt)
{
}
protected void Fill()
{
dtMain = new DataTable();
this.doSelect(dtMain);
if (dtMain == null)
Console.WriteLine("as I would expect");
else
Console.WriteLine("why not changed???");
}
}
}
I tested it with other reference types, but same behavior. Is this a framework bug? When I use the ref keyword it works as I expect:
protected virtual void doSelect(ref DataTable dt)
{
} and so on
Would be nice I anyone could help me with this!
Consider following
class Program
{
static void Main(string[] args)
{
var pr = new Program();
f(pr);
if (pr == null)
Console.WriteLine("Can't happen");
else
Console.WriteLine("Always happen");
}
public static void f(Program prog)
{
prog = null;
}
}
pr variable references to some memory address, let's say namely 0x111111. When you call f method, what really happens is that, prog variable is assigned to same value as pr e.i 0x111111 . when you assign null to prog variable, it makes prog variable to points to null but not pr variable content, nor content stored in 0x111111 is changed. So, pr variable still references to 0x111111 memory address. Same happens in your case.
When you do not use the ref keyword, the parameter is passed by value. If you change the value (i.e. the reference) to refer something else (here null), then that is not reflected on the caller's side.
This is not really related to your use of virtual and override.
An alternative to ref here is to return the new value (instead of returning void), as in:
protected virtual DataTable doSelect(DataTable dt)
{ /* ... */ }
Be sure your method name reflects what the method does.
When doSelect() assigns null to dt, it merely changes the value of the pointer in it's stack frame. However, Fill() has it's own stack frame with it's own "copy" of dtMain. This value had not been changed by doSelect().
Passing a value by ref means passing a pointer to the value inside the caller's (Fill()) stack frame.
It's not a bug.
That's expected behaviour.
Unless you use the ref keyword, you are passing by value, so the value on the "client" side of the method won't change.
Read the MS reference for the ref keyword:
https://msdn.microsoft.com/en-us/library/14akc2c7.aspx
This question already has answers here:
How do I use reflection to call a generic method?
(8 answers)
Closed 8 years ago.
I have a code like this:
if (args.ElementType == typeof(SomeFirstClassName))
{
args.Result = GetResult<SomeFirstClassName>(args);
}
else if (args.ElementType == typeof(SomeSecondClassName))
{
args.Result = GetResult<SomeSecondClassName>(args);
}
How I can simplify this code, if I will have a many types?
For example, can I do something like below?
args.Result = this.GetResult<**args.ElementType**>(args);
I cannot put the variable Type (args.ElementType) to the <>. Is it limitation of C#?
You simplify this without reflection by using a dictionary which maps the type to the method to call.
Here's a sample program to demonstrate:
using System;
using System.Collections.Generic;
namespace Demo
{
public class SomeFirstClassName{}
public class SomeSecondClassName{}
public class Result {}
public class Args
{
public Result Result;
public Type ElementType;
}
internal class Program
{
private Dictionary<Type, Func<Args, Result>> map = new Dictionary<Type, Func<Args, Result>>();
private void run()
{
init();
var args1 = new Args {ElementType = typeof(SomeFirstClassName)};
var args2 = new Args {ElementType = typeof(SomeSecondClassName)};
test(args1); // Calls GetResult<T> for Demo.SomeFirstClassName.
test(args2); // Calls GetResult<T> for Demo.SomeSecondClassName.
}
private void test(Args args)
{
args.Result = map[args.ElementType](args);
}
private void init()
{
map.Add(typeof(SomeFirstClassName), GetResult<SomeFirstClassName>);
map.Add(typeof(SomeSecondClassName), GetResult<SomeSecondClassName>);
}
public Result GetResult<T>(Args args)
{
Console.WriteLine("GetResult<T>() called for T = " + typeof(T).FullName);
return null;
}
private static void Main()
{
new Program().run();
}
}
}
This makes the call site much simpler (args.Result = map[args.ElementType](args);) but you will still have to add an initialiser for each type to the init() method, as shown above.
However this does at least move all the type logic into a single method (init()) which I think is a cleaner and more maintainable design.
However, I can't help but think that there is going to be a much better object-oriented solution to what you're trying to achieve. But we'd need a lot more information about what it is you want to do (this looks like it might be an X-Y problem at the moment).
The answer to your question is to use reflection. However, if you are looking for a non-reflection way of getting around this then you could pass in ElementType in as a parameter
GetResult<TElementType, TArgs>(TElementType elementType, TArgs args)
This would reduce your code to a single call i.e. GetResult(args.ElementType, args). It's not great but it would give you what you want.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Retrieving the calling method name from within a method (C#)
I have a class say A in which there is a Method called Func1; this function is static.
Now there are some other classes say B, C that use A.Func1
How can I get the class name which contains the function that is calling ?
ie
public class A
{
public static void Func1()
{
// who called me?
}
}
public class B
{
public void CallFunc()
{
A.Func1();
}
}
public class C
{
public void AlsoCallFunc()
{
A.Func1();
}
}
Can use StackTrace class in order to acees that kind of information.
To get calling method name, I sometimes use this function. But you need to check if it works in your specific case:
private static string GetCallingMethodName()
{
const int iCallDeepness = 2;
System.Diagnostics.StackTrace stack = new System.Diagnostics.StackTrace(false);
System.Diagnostics.StackFrame sframe = stack.GetFrame(iCallDeepness);
return sframe.GetMethod().Name;
}
if you need to work with form and want to know which form is calling then use event and sender
maybe you work with the output of
Environment.StackTrace