Можно ли хранить оператор в переменной - PullRequest
0 голосов
/ 03 апреля 2020

Интересно, возможно ли сохранить оператор в какой-то переменной? Мой код должен быть понятен.

Но мне интересно, возможно ли сохранить:
<,>,> =
в некоторой переменной и использовать ее в операторе if, как я пытаюсь делать в коде или если есть другой подход для достижения этого?

String compare = "largerValue"; //largerEqualValue, equalValue
var useoperator = "";

if (compare == "largerValue") { useoperator = ">"; }
if (compare == "largerEqualValue") { useoperator = ">="; }
if (compare == "equalValue") { useoperator = "=="; }

for (int i = 0; i < 100000; i++)
{
    if( 20 useoperator 50) { } //Is it possible to assign an "useoperator" like this in any way?
}

Ответы [ 4 ]

4 голосов
/ 03 апреля 2020

Одним из способов может быть сохранение операторов в качестве делегатов в словаре:

var operators = new Dictionary<string, Func<int, int, bool>>();

operators.Add("largerValue", (a, b) => a > b);
operators.Add("largerEqualValue", (a, b) => a >= b);
operators.Add("equalValue", (a, b) => a == b);

Тогда вы можете просто получить и вызвать оператора, когда вам это нужно:

var operator = operators[compare];

for (int i = 0; i < 100000; i++)
{
    if (operator(20, 50)) { } 
}
0 голосов
/ 03 апреля 2020

А как насчет производительности?

Запуск приведенного ниже кода (LinqPad) привел к

1 000 000 000 Собственных операций: 358 930 064 тиков
1 000 000 000 Динамических c операций: 369 853 643 тиков

Поскольку в миллисекунде имеется 10 000 тиков, это работает в:

1 000 000 000 Собственные операции: 35 893 мс
1 000 000 000 Динамические c операции: 36 985 мс

var stopwatch = new Stopwatch();
var iterations = 1_000_000_000;

var rng = new Random();
var greaterThan = 0;

stopwatch.Start();
for (var iteration = 0; iteration < iterations; iteration++){
    var (a, b) = (rng.Next(), rng.Next());

    if (a > b) {
        greaterThan++;
    }
}
stopwatch.Stop();

Console.WriteLine($"{iterations:0,000} Native operations: {stopwatch.ElapsedTicks:0,000} ticks");

Expression<Func<int, int, bool>> GreaterThan = (a, b) => a > b;
var compiled = GreaterThan.Compile();

greaterThan = 0;

stopwatch.Reset();
stopwatch.Start();
for (var iteration = 0; iteration < iterations; iteration++)
{
    var (a, b) = (rng.Next(), rng.Next());

    if (compiled(a,b))
    {
        greaterThan++;
    }
}
stopwatch.Stop();

Console.WriteLine($"{iterations:0,000} Dynamic operations: {stopwatch.ElapsedTicks:0,000} ticks");

То же самое, но с использованием лямбды (Func<int, int, bool>) дало очень похожие результаты:

1 000 000 000 Собственные операции: 354 127 563 тика
1 000 000 000 Динами c операции: 401 450 782 тика

Или:

1 000 000 000 Собственные операции: 35 412 мс
1 000 000 000 Dynami c операции: 40 145 мс

Ускорение

Простой способ ускорить приведенный выше код - удалить случайное число из l oop. Простое использование 2 случайных чисел, сгенерированных до того, как один из разделов по времени значительно сокращает время выполнения, примерно до 3,1 секунды (Native) и 7,9 секунды (Dynami c).

Заключение

Итак в то время как использование динамической операции c вместо собственной операции, по-видимому, занимает вдвое больше времени, общее влияние на производительность, вероятно, будет подавлено остальной частью кода в l oop. Короче говоря, не беспокойтесь об этом, пока это действительно не станет проблемой.

Заключительные мысли

Вполне вероятно, что есть способ улучшить производительность проверки Dynami c но, вероятно, это снизит удобство сопровождения кода.

Отказ от ответственности: Время, показанное здесь, очень субъективно и зависит от специфики c компьютера с кодом

0 голосов
/ 03 апреля 2020

Вы можете создать Fun c, в котором есть делегат, который оценивает ваш результат.

Оформить заказ по следующему коду:

Func<int, int, bool> compareFunc = null;
if (compare == "largerValue")
{
    compareFunc = (a, b) => a > b;
}

if (compare == "largerEqualValue")
{
    compareFunc = (a, b) => a >= b;
}

if (compare == "equalValue")
{
    compareFunc = (a, b) => a == b;
}

for (var i = 0; i < 100000; i++)
{
    if (compareFunc != null && compareFunc(20, 50))
    {

    }
}

0 голосов
/ 03 апреля 2020

Да, это возможно, ваш оператор - простой булев бинарный оператор:

        Func<int, int, bool> useoperator = null;
        String compare = "largerValue"; //largerEqualValue, equalValue

        if (compare == "largerValue") { useoperator = (x,y)=> x > y; }
        if (compare == "largerEqualValue") { useoperator = (x,y)=> x >= y; }
        if (compare == "equalValue") { useoperator = (x,y)=> x == y; }

        for (int i = 0; i < 100000; i++)
        {
            if(useoperator(20, 50)) { }
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...