So let's say I have some number methods that are already defined for a class.
For Example:
private int X(int a, int b)
{
return a + b;
}
private int Y(int a, int b)
{
return a - b;
}
private int Z(int a, int b)
{
return a * b;
}
Now the standard way to take an input in the main body of the class and run it through all the functions would obviously be to just call every function like this:
public void processNormal(int a, int b)
{
//accumulate results
int acc = 0;
if (true)
{
//if want to add to current
acc += X(a, b);
acc += Y(a, b);
acc += Z(a, b);
}
else
{
//if want to replace current if larger
int k = X(a, b);
if (k > acc)
acc = k;
k = Y(a, b);
if (k > acc)
acc = k;
k = Z(a, b);
if (k > acc)
acc = k;
}
}
Now I was curious, since as the number of functions grows, depending on how many things you may want to do with the function results grows, if that doesn't become a bit cumbersome. And you could instead create a static list of the functions you'll want to run, and then use that in a for loop to shorten things down, which I would imagine would look something like this:
//List with all methods
List<Object> methods = new List<Object>();
//add all methods to list
public void processWithList(int a, int b)
{
//accumulate results
int acc = 0;
foreach (Object j in methods)
{
if (true)
{
//if want to add to current
acc += j(a, b);
}
else
{
//if want to replace current if larger
int k = j(a, b);
if (k > acc)
acc = k;
}
}
}
Now with this second process, you still have to define the list somewhere, but I imagine it is easier to keep track of as things grow. All the functions would take the same inputs, and return the same objects so in that regard it's not an issue.
I'm basically wondering if
A) I'm stupidly over complicating things and if this would ever be a useful thing to do.
B) What would such a thing look like in C#? Could I use the predefined class methods in a list or would I have to generate the list in the class' initialization with a bunch of delegate functions?
Thank you for your time.
Am I stupidly over complicating things and if this would ever be a useful thing to do?
No, You're doing just fine. This is a common approach.
What would such a thing look like in C#?
I think the simplest option that matches your sample code is using a List<Func<int, int, int>>.
Here is a sample implementation:
public class YourClass
{
private List<Func<int, int, int>> methods;
public yourClass()
{
methods = new List<Func<int, int, int>>()
{
(a,b) => X(a,b),
(a,b) => Y(a,b),
(a,b) => Z(a,b)
};
}
public int SumMethods(int a, int b)
{
var result = 0;
foreach(var m in methods)
{
result += m(a, b);
}
return result;
}
private int X(int a, int b) { throw new NotImplementedException(); }
private int Y(int a, int b) { throw new NotImplementedException(); }
private int Z(int a, int b) { throw new NotImplementedException(); }
}
Related
This is what I have as an "Add" function in my Maths library:
public static int Add(int a, int b) => a + b;
public static float Add(float a, float b) => a + b;
public static int Add(int a, int b, int c) => a + b + c;
public static float Add(float a, float b, float c) => a + b + c;
public static int Add(int a, int b, int c, int d) => a + b + c + d;
public static float Add(float a, float b, float c, float d) => a + b + c + d;
public static int Add(List<int> numbers)
{
int result = 0;
foreach (int n in numbers) result += n;
return result;
}
public static float Add(List<float> numbers)
{
float result = 0;
foreach (float n in numbers) result += n;
return result;
}
public static int Add(int[] numbers)
{
int result = 0;
foreach (int n in numbers) result += n;
return result;
}
public static float Add(float[] numbers)
{
float result = 0;
foreach (float n in numbers) result += n;
return result;
}
Is there any way to achieve the same result (having a function that works both with int and float and with different parameters) with fewer variations of this function (just to make the code easier to understand)?
EDIT: I'm working with Unity 2022.1.7f1, so for everyone suggesting to use generic math, I don't believe Unity supports C# 11 yet. Please correct me if I'm wrong.
I was able to bring it down from 10 to 4 variations using some recommendations from the comments.
public static int Add(params int[] numbers)
{
return Add(numbers);
//Creates array and calls the next function
}
public static int Add(IEnumerable<int> numbers)
{
int result = 0;
foreach (int n in numbers) result += n;
return result;
}
public static float Add(params float[] numbers)
{
return Add(numbers);
//Creates array and calls the next function
}
public static float Add(IEnumerable<float> numbers)
{
float result = 0;
foreach (float n in numbers) result += n;
return result;
}
If you have any more tips please feel free to share them.
EDIT:
I'm working with Unity 2022.1.7f1, so for everyone suggesting to use generic math, I don't believe Unity supports C# 11 yet. Please correct me if I'm wrong.
UPDATE:
I tried changing IEnumerable<> to List<> and it gives me no errors even if the parameter is an array and not a list, I have not yet tested it's functionality though.
UPDATE:
After testing, it turns out that the first function simply calls itself. I fixed it like this;
public static int Sum(params int[] numbers)
{
List<int> numbersList = new List<int>();
numbersList.AddRange(numbers);
return Sum(numbersList);
}
public static int Sum(List<int> numbers)
{
int result = 0;
foreach (int n in numbers) result += n;
return result;
}
public static float Sum(params float[] numbers)
{
List<float> numbersList = new List<float>();
numbersList.AddRange(numbers);
return Sum(numbersList);
}
public static float Sum(List<float> numbers)
{
float result = 0;
foreach (float n in numbers) result += n;
return result;
}
Also, this makes it so that it is usable with both arrays and lists without the need to use IEnumerables, which means that it can be used in other functions like Min where indexing is necessary.
C# 11 fixes precisely this problem with INumber<T> interface.
https://youtu.be/1K44Nu9_7U8?t=19
Edit: Adding an example with generics since Unity engine might not support C# 11 yet.
namespace GenericCalculations
{
public class GenericMath
{
public static object Add<T>(List<T> listOfT)
{
if (typeof(T) == typeof(int))
{
return listOfT.Sum(t => t as int?);
}
if (typeof(T) == typeof(double))
{
return listOfT.Sum(t => t as double?);
}
// etc
throw new ArgumentException("Invalid entry");
}
}
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
Console.WriteLine(GenericMath.Add(new List<double>() { 1.1, 1.2, 1.3 }));
Console.WriteLine(GenericMath.Add(new List<int>() { 1, 1, 1 }));
}
}
}
I have an example for my problem.
Basically i need to pass a method to another method with parameters included.
public void test() {
var test = Add(Domath(5, 5)); // should be 10
}
public int Domath (int a, int b) {
return a + b;
}
public int Add (Func<int, int, int> math){
return math();
}
It does not work this way and i don‘t know why. This is just a minimalistic example. Is there a way to get this working?
Let's have a look at
public int Add (Func<int, int, int> math){
return math();
}
You can't return return math();: note, that math requires two arguments which are not passed to math(). You can modify Add as
public int Domath (int a, int b){
return a + b;
}
// We are going to add first and second
// with a help of math function
public int Add (int first, int second, Func<int, int, int> math = null) {
// If math is not provided, we use Domath functon
if (math == null)
math = Domath;
// Finally, we call math with required two arguments
return math(first, second);
}
Now you can put
public void test(){
var test = Add(5, 5);
}
Or
public void test(){
var test = Add(5, 5, Domath);
}
I wrote a function that computes recursively the smallest divisor of an integer n>1:
using System;
public class Program
{
public static void Main()
{
int n = Convert.ToInt32(Console.ReadLine());
Console.WriteLine(SmallestDivisor(n));
}
public static int SmallestDivisor(int n)
{
return SmallestDivisor(n, 2);
}
public static int SmallestDivisor(int n, int d)
{
if (n%d == 0)
return d;
else
return SmallestDivisor(n, d+1);
}
}
My goal is to build a recursive function that takes only the integer n as an argument. Is there any possible alternative to avoid calling another auxiliary function taking as arguments integer n and d?
There is no need for 2 method's one is just enough:
static void Main(string[] args)
{
int n = Convert.ToInt32(Console.ReadLine());
Console.WriteLine(SmallestDivisor(n));
}
public static int SmallestDivisor(int n, int d=2)
{
if (n % d == 0)
return d;
return SmallestDivisor(n, ++d);
}
The parameter d is optinal because it has a default value of 2 and you can call the method like SmallestDivisor(n). If you want another value of d passed to the method just call SmallestDivisor(n,d).
replace
public static int SmallestDivisor(int n, int d)
with
public static int SmallestDivisor(int n, int d = 2)
To provide a default value for d and make this parameter optional. Now you can call SmallestDivisor(n) or SmallestDivisor(n,3)
Named and Optional Arguments
recursive method will throw StackOverflow exeption on relatively large prime number (e.g. 15331). non-recursive solution doesn't have such problem
public static int MinimalDivisor(int n)
{
if ( n % 2 == 0)
return 2;
for(int d = 3; d < n/2; d=d+2)
if (n % d == 0)
return d;
return n;
}
I have a python script:
def f():
a = None
b = None
return (a, b)
a, b = f()
It's so easy to achieve multiple return values in python.
And now I want to achieve the same result in C#. I tried several ways, like return int[] or KeyValuePair. But both ways looked not elegant. I wonder a exciting solution. thanks a lot.
Use Tuple class.
public Tuple<int,int> f()
{
Tuple<int,int> myTuple = new Tuple<int,int>(5,5);
return myTuple;
}
Unfortunately, C# does not support this. The closest you can get is to use out parameters:
void f(out int a, out int b) {
a = 42;
b = 9;
}
int a, b;
f(out a, out b);
You can obviously do
object F(out object b)
{
b = null;
return null
}
object b;
var a = F(out b)
but better to use Tuple with a functional style,
Tuple<object, object> F()
{
return Tuple.Create<object, object>(null, null);
}
var r = F();
var a = r.Item1;
var b = r.Item2;
but, since in c# you can be explicit, why not define your return type.
struct FResult
{
public object A;
public object B;
}
FResult F()
{
return new FResult();
}
var r = F();
var a = F.A;
var b = F.B;
This seems like a small price to pay for the semantic benefits.
This feature is available in C#7 with .Net 4.7.
private (string a, string b) f()
{
return (a: null, b: null);
// or simply: return (null, null);
}
var (a, b) = f();
how can i transform a method (that performs a+b and returns the result) from add(a,b) to a.add(b)?
i read this somewhere and i can't remember what is the technique called...
does it depends on the language?
is this possible in javascript?
In .NET it is called extension methods.
public static NumberExtensions
{
public static int Add(this int a, int b)
{
return a + b;
}
}
UPDATE:
In javascript you could do this:
Number.prototype.add = function(b) {
return this + b;
};
var a = 1;
var b = 2;
var c = a.add(b);
On c# it is named extensions methods:
public static class IntExt
{
public static int Add(this int a, int b)
{
return a + b;
}
}
...
int c = a.Add(b);
say for example you want to do this on integers in C#. You need to define extension methods like this:
public static class IntExtMethods
{
public static int add(this int a, int b)
{
return a+b;
}
}
In C# you can use an Extension Method. In C++, you need to create a member which belongs to the A class which performs the add for you. C does not have objects, so what you're looking for is not possible in C.
If you want to create your own JavaScript class:
function Num(v) {
this.val = v;
}
Num.prototype = {
add: function (n) {
return new Num(this.val + n.val);
}
};
var a = new Num(1);
var b = new Num(2);
var c = a.add(b); // returns new Num(3);
Taking your question literally, I assume you mean transforming this
var add = function(a, b) {
return a + b;
}
to this:
a.add = function(b) {
return this + b;
}
This however only adds that method to a, not to any other object with the same constructor. See Darin Dimitrov's answer for an example of that. Extending the native Number constructor's prototype is not something many would recommend though...