📜 ⬆️ ⬇️

Why do we need delegates in C #?

image
Thinking through the architecture of the next class, you understand that it would be very useful for you to pass a piece of executable code as an argument. This would allow you to avoid a string of if-s and case-s and would make your code more elegant. Girls would delightfully groan and certainly leave you their phone number in the comments. Hmm ... something I got carried away.

So how is this done in C #? For example, you write a calculator and you have the simplest logic:
public double PerformOperation(string op, double x, double y)
{
	switch (op)
	{
		case "+": return x + y;
		case "-": return x - y;
		case "*": return x * y;
		case "/": return x / y;
		default: throw new ArgumentException(string.Format("Operation {0} is invalid", op), "op");
	}
}


, :



?

:
switch (op)
{
	case "+": return this.DoAddition(x, y);
	case "-": return this.DoSubtraction(x, y);
	case "*": return this.DoMultiplication(x, y);
	case "/": return this.DoDivision(x, y);
	default: throw new ArgumentException(string.Format("Operation {0} is invalid", op), "op");
}
...
private double DoDivision(double x, double y) { return x / y; }
private double DoMultiplication(double x, double y) { return x * y; }
private double DoSubtraction(double x, double y) { return x - y; }
private double DoAddition(double x, double y) { return x + y; }

:
private delegate double OperationDelegate(double x, double y);
private Dictionary<string, OperationDelegate> _operations;

public Calculator()
{
	_operations =
		new Dictionary<string, OperationDelegate>
		{
			{ "+", this.DoAddition },
			{ "-", this.DoSubtraction },
			{ "*", this.DoMultiplication },
			{ "/", this.DoDivision },
		};
}

public double PerformOperation(string op, double x, double y)
{
	if (!_operations.ContainsKey(op))
		throw new ArgumentException(string.Format("Operation {0} is invalid", op), "op");
	return _operations[op](x, y);
}


? — .
private delegate double OperationDelegate(double x, double y);
private Dictionary<string, OperationDelegate> _operations;


. , . double double. (+-*/) .
: .

,
{ "+", this.DoAddition }
case "+": return x + y;

C# 2.0 :
{ "+", delegate(double x, double y) { return x + y; } },
{ "-", delegate(double x, double y) { return x - y; } },
{ "*", this.DoMultiplication },
{ "/", this.DoDivision },

, . ...

C# 3.0 :
private Dictionary<string, Func<double, double, double>> _operations =
	new Dictionary<string, Func<double, double, double>>
	{
		{ "+", (x, y) => x + y },
		{ "-", (x, y) => x - y },
		{ "*", this.DoMultiplication },
		{ "/", this.DoDivision },
	};

--, — !

Func<double, double, double>  delegate double Delegate(double x, double y)

Func< , , >. Func , . , Func , , . ?


? PerformOperation .
public double PerformOperation(string op, double x, double y)
{
	if (!_operations.ContainsKey(op))
		throw new ArgumentException(string.Format("Operation {0} is invalid", op), "op");
	return _operations[op](x, y);
}


operations . xml-, , . Func<double, double, double>.

C# , .


JavaScript
var operations = { "+": function(x, y) { return x + y; } };

-?

: C# - , . , . .

, .
PerformOperation . DefineOperation Calculator:
public void DefineOperation(string op, Func<double, double, double> body)
{
	if (_operations.ContainsKey(op))
		throw new ArgumentException(string.Format("Operation {0} already exists", op), "op");
	_operations.Add(op, body);
}

:
var calc = new Calculator();
calc.DefineOperation("mod", (x, y) => x % y);
var mod = calc.PerformOperation("mod", 3.0, 2.0);
Assert.AreEqual(1.0, mod);

PerformOperation switch.

')

Source: https://habr.com/ru/post/143925/


All Articles