Перегрузка оператора вызова функции в C#

Действительно ли возможно перегрузить функциональный оператор по умолчанию (() оператор) в C#? Раз так - как? В противном случае есть ли обходное решение для создания подобного влияния?

Спасибо,
Asaf

Править:
Я пытаюсь дать классу оператор по умолчанию, что-то вроде:

class A {
    A(int myvalue) {/*save value*/}

    public static int operator() (A a) {return a.val;}
    ....
   }

...
A a = new A(5);
Console.Write(A());

РЕДАКТИРОВАНИЕ 2:
Я считал спецификацию, и я понимаю, что нет никакого прямого способа сделать это. Я надеялся, что существует обходное решение.

РЕДАКТИРОВАНИЕ 3: мотивация должна сделать класс, или экземпляр ведет себя как функция, для создания удобного интерфейса входа. Между прочим, это выполнимо и разумно в C++.

28
задан Asaf R 15 March 2010 в 20:28
поделиться

5 ответов

Нет, () не является оператором, поэтому его нельзя перегружать. (Это неверно, см. комментарий Эрика Липперта ниже) Круглые скобки являются частью синтаксиса C#, которые используются для выражения набора аргументов, передаваемых методу. () просто указывает, что данный метод не имеет формальных параметров и поэтому не требует аргументов.

Что вы пытаетесь сделать? Возможно, если бы вы привели небольшой пример проблемы, мы смогли бы помочь с решением.

Edit: Хорошо, теперь я понимаю, к чему вы клоните. Вы всегда можете создать делегат, который сопоставляется с методом экземпляра следующим образом (учитывая, что класс A определяет метод следующим образом: public void Foo() { }):

Action action = someA.Foo;

Затем вы могли бы вызвать делегат с помощью простого синтаксиса, например, такого:

action();

К сожалению (или нет, в зависимости от ваших предпочтений), это практически максимальное приближение C# к такому синтаксису.

8
ответ дан 28 November 2019 в 03:23
поделиться

Вы не можете перегрузить () , но вы можете взять объект и сделать делегата (аналогично указателю на функцию) одного из его методов:

class Foo
{ 
    private Bar bar;
    // etc.

    public Baz DoSomething(int n)
    {
        // do something, for instance, 
        // get a Baz somehow from the 'bar' field and your int 'n'
        // ...
    }
}

Теперь DoSomething - это метод, который принимает int и возвращает Baz , который совместим с типом делегата ] Func .
(Есть Action и Action для методов, которые возвращают void и принимают, соответственно, ни одного аргумента, либо один аргумент. Также есть Func и варианты для принятия большего количества аргументов.)

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

void Frob(Func<int, Baz> f)
{
        Baz b = f(5); 
        // do whatever with your baz
}

Наконец, создание делегата и передача его Frob происходит примерно так:

Foo foo = new Foo();
Func<int, Baz> f = new Func<int, Baz>(foo.DoSomething);
Frob(f);

Это хоть как-то помогает? Я до сих пор не совсем понимаю, чего именно вы хотите достичь.

0
ответ дан 28 November 2019 в 03:23
поделиться

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

FooBar MyAlgorithm(Foo paramA, Bar paramB, Actions<string> logger) {
    logger("Starting algorithm.")
    FooBar result = ...;
    logger("Finished algorithm.");
    return result;
}

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

MyAlgorithm(a, b, (text) => Console.WriteLine(text));

Или войдите в текстовое поле Windows Forms:

TextBox logbox = form.GetLogTextBox();
MyAlgorithm(a, b, (text) => logbox.Text += text + Environment.NewLine);
0
ответ дан 28 November 2019 в 03:23
поделиться

Нет. Раздел 7.2.2 спецификации C # определяет перегружаемые операторы как:

UNARY: + -! ~ ++ - true false
BINARY: + - * /% & | ^ << >> ==! => <> = <=

В любом случае ваша удобочитаемость пошла бы к черту. Может быть, есть другой способ добиться того, что вы пытаетесь сделать?

17
ответ дан 28 November 2019 в 03:23
поделиться

Проверьте неявное преобразование . Другой вариант - явное преобразование , но тогда вам нужно будет привести тип объекта.

public class A
{
    public A(int myValue)
    {
        this.MyValue = myValue;
    }
    public int MyValue { get; private set; }

    public static implicit operator int(A a)
    {
        return a.MyValue;
    }
    public static implicit operator A(int value)
    {
        return new A(value);
    }
    // you would need to override .ToString() for Console.WriteLine to notice.
    public override string ToString()
    {
        return this.MyValue.ToString();
    }
}
class Program
{
    static void Main(string[] args)
    {
        A t = 5;
        int r = t;
        Console.WriteLine(t); // 5
    }
}
0
ответ дан 28 November 2019 в 03:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: