MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
C Sharpの基礎 - インターフェイスのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
C Sharpの基礎 - インターフェイス
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == インターフェースとは、クラスが実装すべき規約を定めるものである。<br> インターフェイスには、非抽象クラスまたは構造体で実装する必要がある関連する機能のグループに対する定義が含まれる。<br> <br> 特に、C#はクラスの多重継承ができないため、インターフェイスは重要である。<br> <br> また、C# 8.0以降では、メンバの既定の実装を定義できる。<br> ただし、インターフェイスでは、フィールド、自動実装プロパティ、プロパティに似たイベント等は宣言できない。<br> <br> 構造体を継承する場合は、インターフェイスを使用する必要がある。<br> C#の構造体は、別の構造体またはクラスから継承することができないからである。<br> <br> 以下に、インターフェイスの特徴を示す。<br> * publicの抽象メソッドのみを持つクラスのようなもの。 * インターフェイスを定義する時は、interfaceキーワードを使用する。 * 抽象クラスとは異なり、複数のインターフェースを継承できる。 * C# 8.0以降では、メンバの既定の実装を定義できる。 <br><br> == インターフェース == インターフェースとは、規約のみを定めるものである。<br> <br> C#では、抽象メソッドを使用することでメソッドの規約のみを定めることができる。<br> つまり、C#のインターフェースとは、抽象メソッドのみを持つ抽象クラスだと考えることができる。<br> <br> C#のインターフェースの定義は以下のように記述する。<br> <syntaxhighlight lang="c#"> interface インターフェース名 { // メソッド・プロパティの宣言 } </syntaxhighlight> <br> インターフェースの実装は、クラスの継承と同じ構文である。<br> <syntaxhighlight lang="c#"> class クラス名 : インターフェース名 { // クラスの定義 } </syntaxhighlight> <br> インターフェースには、以下のような特徴がある。 * メンバ変数(フィールド)を持つことができない。 * staticメソッドを持つことができない。 * 宣言したメソッドおよびプロパティは、全て<code>public abstract</code>になる。 * 1つのクラスが複数のインターフェースを実装(多重継承)できる。 <br> C# 8.0では、制限がいくつか緩和されている。<br> 機能面でいうと、クラスと抽象クラスとの差は、<u>メンバ変数(フィールド)を持てない代わりに多重継承できる</u>程度である。<br> <br><br> == 標準クラスライブラリのインターフェース == .NET Frameworkの標準クラスライブラリでは、いくつかの汎用性の高いインターフェースが標準で存在する。<br> 以下では、そのうちのいくつかを記載する。<br> <br> ==== IComparable ==== <code>IComparable<T></code>インターフェイス(<code>System</code>名前空間)は、順序比較ができるものを表す。<br> 配列の整列等に使用する。<br> <syntaxhighlight lang="c#"> using System; using System.Linq; /// <summary> /// 2次元上の点 /// <see cref="IComparable{T}"/> を実装している = 順序をつけられる。 /// </summary> class Point2D : IComparable<Point2D> { public double X { get; } public double Y { get; } public Point2D(double x, double y) { X = x; Y = y; } public double Radius => Math.Sqrt(X * X + Y * Y); public double Angle => Math.Atan2(Y, X); /// <summary> /// 距離で順序を決める。 /// 距離が全く同じなら偏角で順序付け。 /// </summary> /// <param name="other"></param> /// <returns></returns> public int CompareTo(Point2D other) { var r = Radius.CompareTo(other.Radius); if (r != 0) { return r; } return Angle.CompareTo(other.Angle); } } class IComparableSample { public static void Main() { const int N = 5; var rand = new Random(); var data = Enumerable.Range(0, N).Select(_ => new Point2D(rand.NextDouble(), rand.NextDouble())).ToArray(); Console.WriteLine("元:"); foreach (var p in data) WriteLine(p); // 並べ替えの順序に使える Console.WriteLine("整列済み:"); foreach (var p in data.OrderBy(x => x)) WriteLine(p); } private static void WriteLine(Point2D p) { Console.WriteLine($"({p.X:N3}, {p.Y:N3}), radius = {p.Radius:N3}, angle = {p.Angle:N3}"); } } </syntaxhighlight> <br> ==== コレクション ==== コレクションには、同じ操作ができる様々な実装方法がある。(それぞれ、メリットおよびデメリットがある)<br> C#では、操作の種類ごとにインターフェイスが標準で存在しており、コレクションはそれらのインターフェイスを実装する。<br> <br> 下表に、その例を示す。(いずれも<code>System.Collections.Generic</code>名前空間)<br> <center> {| class="wikitable" style="background-color:#fefefe;" |- ! style="background-color:#00ffff;" | インターフェイス ! style="background-color:#00ffff;" | 説明 |- | IEnumerable<T> || 要素の列挙ができる。<br>foreach文やLINQ to Objectsで使用する。 |- | ICollection<T> || IEnumerable<T>に加えて、要素の追加(Add)、削除(Remove)、要素の個数の取得ができる。 |- | IList<T> || ICollection<T>に加えて、インデクサを使用した要素の読み書きができる。 |- | IDictionary<TKey, TValue> || 辞書アクセス(キーを使った値の検索)しての値の読み書きができる。 |- | IReadOnlyCollection<T><br><u>.NET Framework 4.5以降とC# 5.0以降</u> || IEnumerable<T>に加えて、要素の個数を取得できる。<br>読み取り専用なので共変。 |- | IReadOnlyList<T><br><u>.NET Framework 4.5以降とC# 5.0以降</u> || IReadOnlyCollection<T>に加えて、インデクサを使用した要素の読み取りができる。<br>読み取り専用なので共変。 |- | IReadOnlyDictionary<TKey, TValue><br><u>.NET Framework 4.5以降とC# 5.0以降</u> || 辞書アクセス(キーを使った値の検索)しての値の読み取りができる。 |} </center> <br> 上表のうち、<code>IEnumerable<T></code>と<code>IReadIReadOnlyList<T></code>の例を示す。<br> <syntaxhighlight lang="c#"> using System; using System.Collections; using System.Collections.Generic; using System.Linq; /// <summary> /// 連結リスト /// <see cref="IEnumerable{T}"/> を実装している = データの列挙ができる。複数のデータを束ねてる。 /// </summary> /// <typeparam name="T"></typeparam> class LinkedList<T> : IEnumerable<T> { public T Value { get; } public LinkedList<T> Next { get; } public LinkedList(T value) : this(value, null) { } private LinkedList(T value, LinkedList<T> next) { Value = value; Next = next; } public LinkedList<T> Add(T value) => new LinkedList<T>(value, this); public IEnumerator<T> GetEnumerator() { if(Next != null) { foreach (var x in Next) { yield return x; } yield return Value; } } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } class IEnumerableSample { public static void Main() { var a = new LinkedList<int>(1); var b = a.Add(2).Add(3).Add(4); // foreach で使える(これは IEnumerable 必須ではない) foreach (var x in b) Console.WriteLine(x); // string.Join で使える Console.WriteLine(string.Join(", ", b)); // LINQ で使える Console.WriteLine(b.Sum()); } } </syntaxhighlight> <br> <syntaxhighlight lang="c#"> using System; using System.Collections; using System.Collections.Generic; /// <summary> /// 4次元上の点 /// <see cref="IReadOnlyList{T}"/> を実装している = <see cref="IEnumerable{T}"/>に加えて、インデックス指定で値を読める。 /// </summary> class Point4D : IReadOnlyList<double> { public double X { get; } public double Y { get; } public double Z { get; } public double W { get; } public Point4D(double x, double y, double z, double w) { X = x; Y = y; Z = z; W = w; } public double this[int index] { get { switch (index) { default: case 0: return X; case 1: return Y; case 2: return Z; case 3: return W; } } } public int Count => 4; public IEnumerator<double> GetEnumerator() { yield return X; yield return Y; yield return Z; yield return W; } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } class IReadOnlyListSample { public static void Main() { var p1 = new Point4D(1, 2, 3, 4); var p2 = new Point4D(3, 7, 5, 11); // X, Y, Z, W の代わりに 0, 1, 2, 3 のインデックスで値を読み出し var innerProduct = 0.0; for (int i = 0; i < 4; i++) { innerProduct += p1[i] * p2[i]; } Console.WriteLine(innerProduct); } } </syntaxhighlight> <br> ==== IDisposable ==== <code>IDisposable</code>インターフェイス(<code>System</code>名前空間)は、明示的なタイミングで破棄処理を行う場合に使用する。<br> <syntaxhighlight lang="c#"> using System; /// <summary> /// <see cref="IDisposable"/> を実装している = 使い終わったら明示的に Dispose を呼ぶ必要がある。 /// </summary> class Stopwatch : IDisposable { System.Diagnostics.Stopwatch _s = new System.Diagnostics.Stopwatch(); public Stopwatch() { _s.Start(); } public void Dispose() { _s.Stop(); Console.WriteLine(_s.Elapsed); } } class IDisposableSample { public static void Main() { // using ブロックを抜けたら自動的に Dispose が呼ばれる using (new Stopwatch()) { var t = T(12, 6, 0); } } private static int T(int x, int y, int z) => x <= y ? y : T(T(x - 1, y, z), T(y - 1, z, x), T(z - 1, x, y)); } </syntaxhighlight> <br> __FORCETOC__ [[カテゴリ:C_Sharp]]
C Sharpの基礎 - インターフェイス
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse