Поиск

Синтаксис и пример

Итак, перегрузка оператора — это разновидность вызова метода. Для переопределения оператора применяется такой шаблон (здесь on — перегружаемый оператор):
public static возвращаемое_значение operator"/? (объект! [, объект2\) При перегрузке операторов учитывайте следующие факты.

  • Все методы, представляющие перегружаемые операторы, должны быть определены как public и static.
  • Формально возвращаемое^значение может быть любого типа. Однако общая практика — возвращать тип, для которого определяется метод (кроме операторов true и false — они должны всегда возвращать булево значение).
  • Число передаваемых аргументов (объект!, объект!) зависит от типа перегружаемого оператора. Для унарных (т. е. с одним операндом) операторов должен указываться один аргумент. Для перегрузки бинарного (т. е. с двумя операндами) оператора передаются два аргумента.
  • В случае унарных операторов аргумент этого метода должен быть того же типа, что и включенный в него класс или структура. Иначе говоря, если вы переопределяете унарный оператор "!" для класса Foo,
1 В английском языке по звучанию напоминает "синтетический сахар". — Прим. перев.
этот метод в качестве аргумента должен принимать только переменные типа Foo.
  • Если перегружается бинарный оператор, тип первого аргумента должен совпадать с типом вложенного класса, а второй может быть любого типа.

В псевдокоде предыдущего раздела я использовал оператор += с классом Invoice. По причинам, которые скоро будут вам понятны, такие составные операторы на самом деле перегрузить нельзя. Переопределить можно только "базовый" оператор, в данном случае +. Вот синтаксис определения метода operator+ метода Invoice:

public static Invoice operator+
(Invoice invoice!, Invoice invoice2) <
// Создаем новый объект Invoice.
// Добавляем необходимое содержимое из
// invoice! в новый объект Invoice.
// Добавляем необходимое содержимое из
// invoice2 в новый объект Invoice.
// Возвращаем новый объект Invoice. >

Теперь рассмотрим пример, более приближенный к действительности, с двумя классами: Invoice и InvoiceDetailLine. Invoice имеет член-переменную типа Array List, который представляет совокупность позиций из всех счетов. Чтобы можно было суммировать позиции из нескольких счетов, я перегрузил оператор + (см. метод operator+). Метод Invoice.оре-rator+ создает новый объект Invoice и проходит по массивам обоих объектов, добавляя каждую позицию к новому объекту Invoice. Затем этот объект возвращается вызывающему методу. Разумеется, в реальном приложении все будет значительно сложней, а здесь я лишь.показываю, как на самом деле могут перегружаться операторы.

using System;
using System.Collections;
class InvoiceDetailLine {
double lineTotal; public double LineTotal {
get {
return this.lineTotal;
} }
public InvoiceDetailLine(double LineTotal) {
this.lineTotal = LineTotal; } }
class Invoice {
public ArrayList DetailLines;
public InvoiceO {
DetailLines = new ArrayListQ; }
public void Printlnvoice() {
Console.WriteLine("\nn,03vmKfl Nbr\tBcero");
int i = 1;
double total = 0;
foreach(InvoiceDetailLine detailLine in DetailLines)
{
Console.WriteLine("{0}\t\t{1}",
i++, detailLine.LineTotal);
total += detailLine.LineTotal; }
Console.WriteLine("=====\t\t===");
Console.WriteLine("Bcero\t\t{1}", i++, total); }
public static Invoice operator* (Invoice invoicel,
Invoice invoice2) {
Invoice returnlnvoice = new InvoiceO;
foreach (InvoiceDetailLine detailLine in
invoicel.DetailLines) {
returnlnvoice.DetailLines.Add(detailLine); >
foreach (InvoiceDetailLine detailLine in
invoice2.DetailLines) {
returnlnvoice.DetailLines.Add(detailLine); }
return returnlnvoice; } }
class InvoiceAddApp {
public static void Main() {
Invoice 11 = new InvoiceO; for (int i = 0; i < 2; i++) {
11.DetailLines.Add(new InvoiceDetailLine(i + 1)); }
Invoice i2 = new InvoiceO; for (int i = 0; i < 2; i++) <
12.DetailLines.Add(new InvoiceDetailLine(i + 1)); }
Invoice summarylnvoice = it + 12; summarylnvoice.PrintlnvoiceO; } }

Итак, перегрузка оператора — это разновидность вызова метода. Для переопределения оператора применяется такой шаблон (здесь on — перегружаемый оператор):

public static возвращаемое_значение operator"/? (объект! [, объект2\) При перегрузке операторов учитывайте следующие факты.

  • Все методы, представляющие перегружаемые операторы, должны быть определены как public и static.
  • Формально возвращаемое^значение может быть любого типа. Однако общая практика — возвращать тип, для которого определяется метод (кроме операторов true и false — они должны всегда возвращать булево значение).
  • Число передаваемых аргументов (объект!, объект!) зависит от типа перегружаемого оператора. Для унарных (т. е. с одним операндом) операторов должен указываться один аргумент. Для перегрузки бинарного (т. е. с двумя операндами) оператора передаются два аргумента.
  • В случае унарных операторов аргумент этого метода должен быть того же типа, что и включенный в него класс или структура. Иначе говоря, если вы переопределяете унарный оператор "!" для класса Foo,
1 В английском языке по звучанию напоминает "синтетический сахар". — Прим. перев.
этот метод в качестве аргумента должен принимать только переменные типа Foo.
  • Если перегружается бинарный оператор, тип первого аргумента должен совпадать с типом вложенного класса, а второй может быть любого типа.

В псевдокоде предыдущего раздела я использовал оператор += с классом Invoice. По причинам, которые скоро будут вам понятны, такие составные операторы на самом деле перегрузить нельзя. Переопределить можно только "базовый" оператор, в данном случае +. Вот синтаксис определения метода operator+ метода Invoice:

public static Invoice operator+ (
Invoice invoice!, Invoice invoice2) <
// Создаем новый объект Invoice.
// Добавляем необходимое содержимое из
// invoice! в новый объект Invoice.
// Добавляем необходимое содержимое из
// invoice2 в новый объект Invoice.
// Возвращаем новый объект Invoice. >

Теперь рассмотрим пример, более приближенный к действительности, с двумя классами: Invoice и InvoiceDetailLine. Invoice имеет член-переменную типа Array List, который представляет совокупность позиций из всех счетов. Чтобы можно было суммировать позиции из нескольких счетов, я перегрузил оператор + (см. метод operator+). Метод Invoice.оре-rator+ создает новый объект Invoice и проходит по массивам обоих объектов, добавляя каждую позицию к новому объекту Invoice. Затем этот объект возвращается вызывающему методу. Разумеется, в реальном приложении все будет значительно сложней, а здесь я лишь.показываю, как на самом деле могут перегружаться операторы.

using System;
using System.Collections;
class InvoiceDetailLine {
double lineTotal; public double LineTotal {
get {
return this.lineTotal;
} }
public InvoiceDetailLine(double LineTotal) {
this.lineTotal = LineTotal; } }
class Invoice {
public ArrayList DetailLines;
public InvoiceO {
DetailLines = new ArrayListQ; }
public void Printlnvoice() {
Console.WriteLine("\nn,03vmKfl Nbr\tBcero");
int i = 1;
double total = 0;
foreach(InvoiceDetailLine detailLine in DetailLines)
{
Console.WriteLine("{0}\t\t{1}", i++, detailLine.LineTotal);
total += detailLine.LineTotal; }
Console.WriteLine("=====\t\t===");
Console.WriteLine("Bcero\t\t{1}", i++, total); }
public static Invoice operator* (Invoice invoicel,
Invoice invoice2) {
Invoice returnlnvoice = new InvoiceO;
foreach (InvoiceDetailLine detailLine in
invoicel.DetailLines) {
returnlnvoice.DetailLines.Add(detailLine); >
foreach (InvoiceDetailLine detailLine in
invoice2.DetailLines) {
returnlnvoice.DetailLines.Add(detailLine); }
return returnlnvoice; } }
class InvoiceAddApp {
public static void Main() {
Invoice 11 = new InvoiceO;
for (int i = 0; i < 2; i++) {
11.DetailLines.Add(new InvoiceDetailLine(i + 1)); }
Invoice i2 = new InvoiceO; for (int i = 0; i < 2; i++) <
12.DetailLines.Add(new InvoiceDetailLine(i + 1)); }
Invoice summarylnvoice = it + 12;
summarylnvoice.PrintlnvoiceO; } }