Действительно ли возможно перегрузить функциональный оператор по умолчанию (() оператор) в 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++.
Нет, (Это неверно, см. комментарий Эрика Липперта ниже) Круглые скобки являются частью синтаксиса C#, которые используются для выражения набора аргументов, передаваемых методу. ()
не является оператором, поэтому его нельзя перегружать. ()
просто указывает, что данный метод не имеет формальных параметров и поэтому не требует аргументов.
Что вы пытаетесь сделать? Возможно, если бы вы привели небольшой пример проблемы, мы смогли бы помочь с решением.
Edit: Хорошо, теперь я понимаю, к чему вы клоните. Вы всегда можете создать делегат, который сопоставляется с методом экземпляра следующим образом (учитывая, что класс A
определяет метод следующим образом: public void Foo() { }
):
Action action = someA.Foo;
Затем вы могли бы вызвать делегат с помощью простого синтаксиса, например, такого:
action();
К сожалению (или нет, в зависимости от ваших предпочтений), это практически максимальное приближение C# к такому синтаксису.
Вы не можете перегрузить ()
, но вы можете взять объект и сделать делегата (аналогично указателю на функцию) одного из его методов:
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);
Это хоть как-то помогает? Я до сих пор не совсем понимаю, чего именно вы хотите достичь.
Вы упомянули, что хотите вести журнал, вот как вы можете сделать это с делегатами:
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);
Нет. Раздел 7.2.2 спецификации C # определяет перегружаемые операторы как:
UNARY: + -! ~ ++ - true false
BINARY: + - * /% & | ^ << >> ==! => <> = <=
В любом случае ваша удобочитаемость пошла бы к черту. Может быть, есть другой способ добиться того, что вы пытаетесь сделать?
Проверьте неявное преобразование . Другой вариант - явное преобразование , но тогда вам нужно будет привести тип объекта.
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
}
}