2018-08-02 22:04:49 +03:00
|
|
|
|
<html>
|
|
|
|
|
|
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e">
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<param name="Keyword" value="Методы расширения">
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<param name="Keyword" value="extensionmethod">
|
|
|
|
|
|
</object>
|
|
|
|
|
|
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
|
|
|
|
|
|
<title></title>
|
|
|
|
|
|
<link rel="StyleSheet" href="../../default.css">
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
|
|
<body>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<H1>Методы расширения</H1>
|
|
|
|
|
|
<p>Любой существующий тип, хранящийся во внешней dll, и все типы стандартной
|
|
|
|
|
|
библитеки .NET можно расширить новыми методами. Метод расширения определяется
|
|
|
|
|
|
как процедура или функция с модификатором <code> <strong>
|
|
|
|
|
|
extensionmethod</strong></code>. Первый параметр метода расширения
|
|
|
|
|
|
обязательно должен иметь имя Self и принадлежит к расширяемому типу. Сравним две
|
|
|
|
|
|
процедуры, описанные ниже:</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote><code><strong>procedure</strong> MyPrint(Self: integer);<br><strong>begin</strong><br> writeln(Self)<br>
|
|
|
|
|
|
<strong>end</strong>;<br>
|
|
|
|
|
|
<strong><br>procedure</strong> MyPrintEx(Self: integer); <strong>
|
|
|
|
|
|
extensionmethod</strong>;<br><strong>begin</strong><br> writeln(Self)<br>
|
|
|
|
|
|
<strong>end</strong>;<br>
|
|
|
|
|
|
<br><strong>begin<br></strong> MyPrint(1);<br> 1.MyPrintEx;<br>
|
|
|
|
|
|
<strong>end</strong>.</code></blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>Здесь MyPrint - это обычная процедура с параметром типа integer, MyPrintEx -
|
|
|
|
|
|
метод расширения типа integer. При этом при вызове первый параметр MyPrintEx
|
|
|
|
|
|
становится объектом, вызывающим MyPrintEx как метод.</p>
|
|
|
|
|
|
<p>Можно расширить тип последовательности, тогда все классы, являющиеся
|
|
|
|
|
|
последовательностями (динамические одномерные массивы, списки List<T>, множества
|
|
|
|
|
|
HashSet<T> и SortedSet<T>),
|
|
|
|
|
|
получат этот метод. Например, в системном модуле PABCSystem так введен метод
|
|
|
|
|
|
расширения ForEach для последовательностей:</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<blockquote><code><strong>procedure</strong> &ForEach<T>(Self: <strong>sequence
|
|
|
|
|
|
of</strong> T; action: T -> ()); <strong>extensionmethod</strong>;<br>
|
|
|
|
|
|
<strong>begin</strong><br> <strong>foreach</strong> x: T <strong>in</strong>
|
|
|
|
|
|
Self <strong>do</strong><br> action(x);<br><strong>end</strong>;</code></blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>С помощью методов расширения можно <a href="operoverloading.html">перегружать
|
|
|
|
|
|
операции</a>:</p>
|
2019-01-26 11:43:27 +03:00
|
|
|
|
<blockquote><code><strong>procedure operator</strong>+=<T>(a: List<T>; x: T):
|
2018-08-02 22:04:49 +03:00
|
|
|
|
List<T>; <strong>extensionmethod</strong>;<br><strong>begin</strong><br>
|
2019-01-26 11:43:27 +03:00
|
|
|
|
a.Add(x);<br><strong>end</strong>;</code></blockquote>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<p>В этом случае первый параметр не обязан иметь имя Self.</p>
|
|
|
|
|
|
<p>Для методов расширения имеется ряд ограничений:</p>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
<ul>
|
2025-11-07 16:12:31 +03:00
|
|
|
|
<li>Методы расширения не могут быть виртуальными.</li>
|
|
|
|
|
|
<li>Если метод расширения имеет то же имя, что и обычный метод, то
|
|
|
|
|
|
предпочтение отдаётся обычному методу. </li>
|
2018-08-02 22:04:49 +03:00
|
|
|
|
</ul>
|
|
|
|
|
|
<p> </p>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
|
|
|
|
|
|
</html>
|