Heim Backend-Entwicklung C#.Net-Tutorial Analyse der C#-Erweiterungsmethode

Analyse der C#-Erweiterungsmethode

Feb 07, 2017 pm 03:05 PM
c#

Im Prozess der Projektentwicklung mit objektorientierten Sprachen wird häufig die Funktion „Vererbung“ verwendet, aber nicht alle Szenarien sind für die Verwendung der Funktion „Vererbung“ geeignet. Es werden auch einige Grundprinzipien von Entwurfsmustern erwähnt .

Probleme, die durch die Verwendung vererbungsbezogener Funktionen verursacht werden: Die Vererbungsbeziehung von Objekten wird tatsächlich zur Kompilierungszeit definiert, sodass die von der übergeordneten Klasse geerbte Implementierung zur Laufzeit nicht geändert werden kann. Die Implementierung einer Unterklasse ist so eng von ihrer übergeordneten Klasse abhängig, dass alle Änderungen an der Implementierung der übergeordneten Klasse unweigerlich Änderungen in der Unterklasse nach sich ziehen.

Wenn Sie eine Unterklasse wiederverwenden müssen und die geerbte Implementierung nicht zur Lösung des neuen Problems geeignet ist, muss die übergeordnete Klasse sie neu schreiben oder durch andere, besser geeignete Klassen ersetzt werden. Diese Abhängigkeit schränkt die Flexibilitätseigenschaften ein und schränkt sie letztendlich ein Wiederverwendbarkeit. Als Alternative zur Vererbung von Funktionen werden die meisten das Prinzip der Wiederverwendung von Komposition/Aggregation übernehmen, „Prinzip der Wiederverwendung von Komposition/Aggregation“: Verwenden Sie Komposition/Aggregation so weit wie möglich und versuchen Sie, keine Klassenvererbung zu verwenden.

Die Verwendung von Vererbungsfunktionen kann manchmal ungeeignet sein, wenn der neue Objekttyp Details über zusätzliches Verhalten enthalten soll, beispielsweise beim Umgang mit Referenztypen, versiegelten Klassen oder Schnittstellen. Angesichts dieser Anforderungen schreiben wir manchmal einige statische Klassen, die einige statische Methoden enthalten. Aber zu viele statische Methoden verursachen zusätzlichen unnötigen Overhead.

1. Übersicht über Erweiterungsmethoden:

Angesichts der oben genannten Probleme bezüglich der „Vererbung“ und bei einigen Anforderungen des Projekts müssen wir diese Probleme mit „Erweiterungsmethoden“ lösen. ". In C# 3.0 wurden „Erweiterungsmethoden“ eingeführt, die nicht nur die Vorteile statischer Methoden bieten, sondern auch die Lesbarkeit des Codes verbessern, der sie aufruft. Bei der Verwendung von Erweiterungsmethoden können Sie statische Methoden genauso wie Instanzmethoden aufrufen.

1. Grundprinzipien von Erweiterungsmethoden:

(1) C# unterstützt nur Erweiterungsmethoden und keine erweiterten Attribute, erweiterten Ereignisse, erweiterten Operatoren usw.

(2). Erweiterungsmethoden (Methoden, denen dieser Parameter vorangestellt ist) müssen in einer nicht generischen statischen Klasse deklariert werden, und nur der erste Parameter ist damit gekennzeichnet . .

(3) Wenn der C#-Compiler nach Erweiterungsmethoden in statischen Klassen sucht, müssen diese statischen Klassen selbst einen Dateibereich haben.

(4).C#-Kompilierung erfordert das „Importieren“ von Erweiterungsmethoden. (Statische Methoden können beliebig benannt werden. Wenn der C#-Compiler nach Methoden sucht, dauert die Suche einige Zeit. Er muss alle statischen Klassen im Dateibereich überprüfen und alle ihre statischen Methoden scannen, um eine Übereinstimmung zu finden.)

(5). Mehrere statische Klassen können dieselbe Erweiterungsmethode definieren.

(6) Wenn ein Typ mit einer Erweiterungsmethode erweitert wird, wird auch der abgeleitete Typ erweitert.

2. Deklaration der Erweiterungsmethode:

(1) Es muss sich um eine nicht verschachtelte, nicht generische statische Klasse handeln (also eine statische Methode)

(2).Es gibt mindestens einen Parameter.

(3) Dem ersten Parameter muss das Schlüsselwort this vorangestellt werden.

(4) Der erste Parameter darf keine anderen Modifikatoren haben (z. B. ref oder out).

(5) Der Typ des ersten Parameters darf kein Zeigertyp sein.

In den obigen beiden Klassifizierungsbeschreibungen wird eine kurze Einführung in die grundlegenden Merkmale und Deklarationsmethoden von Erweiterungsmethoden gegeben. Die Verwendung von Erweiterungsmethoden wird in den folgenden Codebeispielen erneut erläutert.

2. Analyse des Prinzips der Erweiterungsmethode:

„Erweiterungsmethode“ ist eine für C# einzigartige Methode und das Attribut ExtensionAttribute wird in der Erweiterungsmethode verwendet.

C# Sobald der erste Parameter einer statischen Methode mit dem Schlüsselwort this markiert ist, wendet der Compiler intern ein benutzerdefiniertes Attribut auf die Methode an. Dieses Attribut wird in die Metadaten der endgültig generierten Datei aufgenommen Speicher befindet sich diese Eigenschaft in der System.Core-DLL-Assembly.

Solange eine statische Klasse mindestens eine Erweiterungsmethode enthält, wird dieses Attribut auch auf ihre Metadaten angewendet. Jede Assembly, die mindestens eine statische Klasse enthält, die die oben genannten Merkmale erfüllt, wird auch auf ihre Metadaten angewendet . Dieses Attribut. Wenn der Code auf eine Instanzmethode verweist, die nicht vorhanden ist, scannt der Compiler schnell alle referenzierten Assemblys, um festzustellen, welche davon Erweiterungsmethoden enthalten. Anschließend kann er innerhalb dieser Assembly statische Klassen scannen, die Erweiterungsmethoden enthalten.

Wenn zwei Klassen im selben Namespace Methoden mit demselben Erweiterungstyp enthalten, gibt es keine Möglichkeit, die Erweiterungsmethode nur in einer der Klassen zu verwenden. Um einen Typ anhand seines einfachen Namens (ohne das Namenskontrollpräfix) zu verwenden, können Sie alle Namespaces importieren, in denen der Typ vorhanden ist. Wenn Sie dies tun, können Sie jedoch nicht verhindern, dass auch Erweiterungsmethoden in diesem Namespace importiert werden .

Drei..NET3.5-Erweiterungsmethoden Aufzählbar und abfragbar:

Im Framework besteht der Hauptzweck von Erweiterungsmethoden darin, LINQ zu bedienen. Das Framework stellt zusätzliche Erweiterungsmethoden bereit, die sich im System befinden. Aufzählbare und abfragbare Klassen unter dem Linq-Namespace. Die meisten Erweiterungen von Enumerable sind IEnumerable und die meisten Erweiterungen von Queryable sind IQueryable.

1. Gängige Methoden in der Enumerable-Klasse

(1).Range(): Ein Parameter ist die Startnummer und der andere ist die Anzahl der zu generierenden Ergebnisse.

public static IEnumerable<int> Range(int start, int count) { 
            long max = ((long)start) + count - 1;
            if (count < 0 || max > Int32.MaxValue) throw Error.ArgumentOutOfRange("count"); 
            return RangeIterator(start, count);
        }
        static IEnumerable<int> RangeIterator(int start, int count) { 
            for (int i = 0; i < count; i++) yield return start + i;
}
Nach dem Login kopieren


(2).Where():对集合进行过滤的一个方式,接受一个谓词,并将其应用于原始集合中的每个元素。

public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
            if (source == null) throw Error.ArgumentNull("source"); 
            if (predicate == null) throw Error.ArgumentNull("predicate"); 
            if (source is Iterator<TSource>) return ((Iterator<TSource>)source).Where(predicate);
if (source is TSource[]) return new WhereArrayIterator<TSource>((TSource[])source, predicate); 
if (source is List<TSource>) return new WhereListIterator<TSource>((List<TSource>)source, predicate);
            return new WhereEnumerableIterator<TSource>(source, predicate);
        }
 public WhereEnumerableIterator(IEnumerable<TSource> source, Func<TSource, bool> predicate) { 
                this.source = source;
                this.predicate = predicate; 
}
Nach dem Login kopieren


以上分别介绍了Range()和Where()两个方法,该类中还主要包含select()、orderby()等等方法。


2.Queryable类中的常用方法:


(1).IQueryable接口:


/// <summary>
  /// 提供对未指定数据类型的特定数据源的查询进行计算的功能。
  /// </summary>
  /// <filterpriority>2</filterpriority>
  public interface IQueryable : IEnumerable
  {
    /// <summary>
    /// 获取与 <see cref="T:System.Linq.IQueryable"/> 的实例关联的表达式目录树。
    /// </summary>
    /// 
    /// <returns>
    /// 与 <see cref="T:System.Linq.IQueryable"/> 的此实例关联的 <see cref="T:System.Linq.Expressions.Expression"/>。
    /// </returns>
    Expression Expression { get; }
    /// <summary>
    /// 获取在执行与 <see cref="T:System.Linq.IQueryable"/> 的此实例关联的表达式目录树时返回的元素的类型。
    /// </summary>
    /// 
    /// <returns>
    /// 一个 <see cref="T:System.Type"/>,表示在执行与之关联的表达式目录树时返回的元素的类型。
    /// </returns>
    Type ElementType { get; }
    /// <summary>
    /// 获取与此数据源关联的查询提供程序。
    /// </summary>
    /// 
    /// <returns>
    /// 与此数据源关联的 <see cref="T:System.Linq.IQueryProvider"/>。
    /// </returns>
    IQueryProvider Provider { get; }
  }
Nach dem Login kopieren


(2).Where():

public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate) { 
            if (source == null)
                throw Error.ArgumentNull("source"); 
            if (predicate == null)
                throw Error.ArgumentNull("predicate");
            return source.Provider.CreateQuery<TSource>(
                Expression.Call( 
                    null,
                    ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource)), 
                    new Expression[] { source.Expression, Expression.Quote(predicate) } 
                    ));
        }
Nach dem Login kopieren



(3).Select():

public static IQueryable<TResult> Select<TSource,TResult>(this IQueryable<TSource> source, Expression<Func<TSource, TResult>> selector) {
            if (source == null)
                throw Error.ArgumentNull("source");
            if (selector == null) 
                throw Error.ArgumentNull("selector");
            return source.Provider.CreateQuery<TResult>( 
                Expression.Call( 
                    null,
                    ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(typeof(TSource), typeof(TResult)), 
                    new Expression[] { source.Expression, Expression.Quote(selector) }
                    ));
}
Nach dem Login kopieren


以上是对扩展方法中两个类进行了一个简单的解析。


四.扩展方法实例:


由于扩展方法实际是对一个静态方法的调用,所以CLR不会生成代码对调用方法的表达式的值进行null值检查


1.异常处理代码:


  /// <summary>
    /// 为参数验证提供有用的方法
    /// </summary>
    public static class ArgumentValidator
    {
        /// <summary>
        /// 如果argumentToValidate为空,则抛出一个ArgumentNullException异常
        /// </summary>
        public static void ThrowIfNull(object argumentToValidate, string argumentName)
        {
            if (null == argumentName)
            {
                throw new ArgumentNullException("argumentName");
            }
            if (null == argumentToValidate)
            {
                throw new ArgumentNullException(argumentName);
            }
        }
        /// <summary>
        /// 如果argumentToValidate为空,则抛出一个ArgumentException异常
        /// </summary>
        public static void ThrowIfNullOrEmpty(string argumentToValidate, string argumentName)
        {
            ThrowIfNull(argumentToValidate, argumentName);
            if (argumentToValidate == string.Empty)
            {
                throw new ArgumentException(argumentName);
            }
        }
        /// <summary>
        /// 如果condition为真,则抛出ArgumentException异常
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="msg"></param>
        public static void ThrowIfTrue(bool condition, string msg)
        {
            ThrowIfNullOrEmpty(msg, "msg");
            if (condition)
            {
                throw new ArgumentException(msg);
            }
        }
        /// <summary>
        /// 如果指定目录存在该文件则抛出FileNotFoundException异常
        /// </summary>
        /// <param name="fileSytemObject"></param>
        /// <param name="argumentName"></param>
        public static void ThrowIfDoesNotExist(FileSystemInfo fileSytemObject, String argumentName)
        {
            ThrowIfNull(fileSytemObject, "fileSytemObject");
            ThrowIfNullOrEmpty(argumentName, "argumentName");
            if (!fileSytemObject.Exists)
            {
                throw new FileNotFoundException("&#39;{0}&#39; not found".Fi(fileSytemObject.FullName));
            }
        }
        public static string Fi(this string format, params object[] args)
        {
            return FormatInvariant(format, args);
        }
        /// <summary>
        /// 格式化字符串和使用<see cref="CultureInfo.InvariantCulture">不变的文化</see>.
        /// </summary>
        /// <remarks>
        /// <para>这应该是用于显示给用户的任何字符串时使用的“B”>“B”>“”。它意味着日志
        ///消息,异常消息,和其他类型的信息,不使其进入用户界面,或不会
        ///无论如何,对用户都有意义;).</para>
        /// </remarks>
        public static string FormatInvariant(this string format, params object[] args)
        {
            ThrowIfNull(format, "format");
            return 0 == args.Length ? format : string.Format(CultureInfo.InvariantCulture, format, args);
        }
        /// <summary>
        /// 如果时间不为DateTimeKind.Utc,则抛出ArgumentException异常
        /// </summary>
        /// <param name="argumentToValidate"></param>
        /// <param name="argumentName"></param>
        public static void ThrowIfNotUtc(DateTime argumentToValidate, String argumentName)
        {
            ThrowIfNullOrEmpty(argumentName, "argumentName");
            if (argumentToValidate.Kind != DateTimeKind.Utc)
            {
                throw new ArgumentException("You must pass an UTC DateTime value", argumentName);
            }
        }
}
Nach dem Login kopieren


2.枚举扩展方法:

public static class EnumExtensions
    {
        /// <summary>
        /// 获取名字
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        public static string GetName(this Enum e)
        {
            return Enum.GetName(e.GetType(), e);
        }
        /// <summary>
        /// 获取名字和值
        /// </summary>
        /// <param name="enumType">枚举</param>
        /// <param name="lowerFirstLetter">是否转化为小写</param>
        /// <returns></returns>
        public static Dictionary<string, int> GetNamesAndValues( this Type enumType, bool lowerFirstLetter)
        {
//由于扩展方法实际是对一个静态方法的调用,所以CLR不会生成代码对调用方法的表达式的值进行null值检查
            ArgumentValidator.ThrowIfNull(enumType, "enumType");
            //获取枚举名称数组
            var names = Enum.GetNames(enumType);
            //获取枚举值数组
            var values = Enum.GetValues(enumType);
            var d = new Dictionary<string, int>(names.Length);
            for (var i = 0; i < names.Length; i++)
            {
                var name = lowerFirstLetter ? names[i].LowerFirstLetter() : names[i];
                d[name] = Convert.ToInt32(values.GetValue(i));
            }
            return d;
        }
        /// <summary>
        /// 转换为小写
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string LowerFirstLetter(this string s)
        {
            ArgumentValidator.ThrowIfNull(s, "s");
            return char.ToLowerInvariant(s[0]) + s.Substring(1);
        }
    }
Nach dem Login kopieren

五.总结:

在本文中,主要对扩展方法进行了一些规则说明、声明方式,使用方式,以及对扩展方法的意义和扩展方法的原理进行了简单的解答。并在本文的最后给了一个枚举的扩展方法代码。

以上就是C#的扩展方法解析的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Beste grafische Einstellungen
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. So reparieren Sie Audio, wenn Sie niemanden hören können
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Chat -Befehle und wie man sie benutzt
1 Monate vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Active Directory mit C# Active Directory mit C# Sep 03, 2024 pm 03:33 PM

Leitfaden zu Active Directory mit C#. Hier besprechen wir die Einführung und die Funktionsweise von Active Directory in C# sowie die Syntax und das Beispiel.

C#-Serialisierung C#-Serialisierung Sep 03, 2024 pm 03:30 PM

Leitfaden zur C#-Serialisierung. Hier besprechen wir die Einführung, die Schritte des C#-Serialisierungsobjekts, die Funktionsweise bzw. das Beispiel.

Zufallszahlengenerator in C# Zufallszahlengenerator in C# Sep 03, 2024 pm 03:34 PM

Leitfaden zum Zufallszahlengenerator in C#. Hier besprechen wir die Funktionsweise des Zufallszahlengenerators, das Konzept von Pseudozufallszahlen und sicheren Zahlen.

C#-Datenrasteransicht C#-Datenrasteransicht Sep 03, 2024 pm 03:32 PM

Leitfaden zur C#-Datenrasteransicht. Hier diskutieren wir die Beispiele, wie eine Datenrasteransicht aus der SQL-Datenbank oder einer Excel-Datei geladen und exportiert werden kann.

Muster in C# Muster in C# Sep 03, 2024 pm 03:33 PM

Leitfaden zu Mustern in C#. Hier besprechen wir die Einführung und die drei wichtigsten Arten von Mustern in C# zusammen mit ihren Beispielen und der Code-Implementierung.

Primzahlen in C# Primzahlen in C# Sep 03, 2024 pm 03:35 PM

Leitfaden zu Primzahlen in C#. Hier besprechen wir die Einführung und Beispiele von Primzahlen in C# sowie die Codeimplementierung.

Fakultät in C# Fakultät in C# Sep 03, 2024 pm 03:34 PM

Leitfaden zur Fakultät in C#. Hier diskutieren wir die Einführung in die Fakultät in C# zusammen mit verschiedenen Beispielen und Code-Implementierungen.

Der Unterschied zwischen Multithreading und asynchronem C# Der Unterschied zwischen Multithreading und asynchronem C# Apr 03, 2025 pm 02:57 PM

Der Unterschied zwischen Multithreading und Asynchron besteht darin, dass Multithreading gleichzeitig mehrere Threads ausführt, während asynchron Operationen ausführt, ohne den aktuellen Thread zu blockieren. Multithreading wird für rechenintensive Aufgaben verwendet, während asynchron für die Benutzerinteraktion verwendet wird. Der Vorteil des Multi-Threading besteht darin, die Rechenleistung zu verbessern, während der Vorteil von Asynchron nicht darin besteht, UI-Threads zu blockieren. Die Auswahl von Multithreading oder Asynchron ist von der Art der Aufgabe abhängt: Berechnungsintensive Aufgaben verwenden Multithreading, Aufgaben, die mit externen Ressourcen interagieren und die UI-Reaktionsfähigkeit asynchron verwenden müssen.

See all articles