==プログラミングC# 第7版(1)==
[[言語 まとめ C#][C#][C# サンプルコード][Effective C# 4.0][Universal Windows Platform][Visual Studio]]
*プログラミングC# 第7版
*プログラミングC# 第7版(2)
**プロジェクトのプロパティで別の名前を指定可能
====推奨====
<<blockquote>>{企業名}.{技術名}.{機能名}.{サブ名前空間}<</blockquote>>
Microsoft.AspNet.Identity.OWIN
====別名====
<<blockquote>>using 別名 = 名前空間<</blockquote>>
using Hg = Foo.Bar.Hoge;
var h = new Hg.Hoge();
|}
<<blockquote>>※1 例えば、dllで宣言された const を exe で参照コンパイル後、dllの const値を変更、dllを差し替えてもexeの値は、元のまま。将来的にも不変な値だけをconstとすべき。読み取り専用の値はreadonly とまずはするとよい<</blockquote>>
===宣言空間===
=====同じ名前が2つの異なる実体を参照してはいけない範囲=====
|-
|}
<<blockquote>>どちらも利用できるが、一般的にはエイリアスを優先して使用する<</blockquote>>
=====数値リテラル=====
===クラス===
=====キーワードclassで定義された型はすべて参照型=====
=====Nullable<<T>>=====
*値型に対してもnullを許容するラッパー
*Nullable<<int>>
**int 型だが null を持てる
===構造体===
{
int result = 0;
nums.ToList().ForEach(x => > result += x);
return result;
}
===インデクサ===
*1つ以上の引数をとるプロパティで配列で用いられるのと同じ構文を使ってアクセス可能
var nums = new List<<int> > { 1,2,3 };
nums[2] += nums[1];
*インデクサのおかげで普通の配列のように利用できる
public string this[int index] {
get {
return index < < 5 ? "Foo":"Bar";
}
}
*特定の演算子ではペアで定義することが必要
**==,!=
**>>,<<
=====カスタム型変換=====
public static explicit operator int(Counter value) {
====匿名型のリスト====
var list = new List<<dynamic>>();
list.Add(new { Id="123",Name="abc" });
===部分型とメソッド===
*コンパイル時に別の型に置き換えることを可能とする
*プレースホルダー
*List<<T> > の T
====ジェネリック型====
*クラス、構造体、インターフェースはすべてジェネリックになることができる
public class Hoge<<T> > {
public Hoge(T x, string name) {
...
====制約====
*:型引数が特定の要請を満たさなければならいことを明示できる
public static class Deferred<<T> > where T : new() {
private static T _instance;
public static T Instance {
====型制約====
*特定の型と互換
public class Hoge<<T> > : ICompara<<T> > where T : IComparable<<T> > { ... }
====参照型制約====
public class Hoge<<T> > where T : class { ... }
*型引数を参照型に限定
*可能となる
**他のジェネリック型が使用できる
====値型制約====
public class Hoge<<T> > where T : struct { ... }
*型引数を値型に制約
*int など組み込み算術型に対しても有効
*Nullable<<T> > はこの制約を使用している
**通常、int? のように記述する
====複数の制約====
*1つの型引数に対して複数の制約を課したい場合、リストとして並べる
public class Hoge<<T> > where T : IEnumerable<<T>>, IDisposable, new() { ... }
====ゼロ系の値====
*default(型)
*その型のデフォルトの初期値
*ジェネリックな型パラメータに対しても使用できる
static void PrintDefault<<T>>() {
Console.WirteLine(default(T));
}
====ジェネリックメソッド====
public static T GetLast<<T>>(T[] items) {
return item[item.Length -1 ];
}
int[] values = {1,2,3};
int last = GetLast<<int>>(values);
*ジェネリック型の中でも、以外でも定義できる
====型推論====
*C++のテンプレートとは全く異なる
==コレクション==
<<blockquote>>C#1.0から提供されているSystem.Collections と、System.Collections.Generic に分類できる。前者は古いライブラリで、ジェネリックに対応しておらず、現在ではほぼ利用しない。<</blockquote>>
===分類===
{|class="wikitable"
**要素探索を行う最も素直な方法
*Array.FindIndex
int x = Array.FindIndex(nums, x=> > x>>0);
*Array.FidAll
**該当する複数要素
*Array.Reverse
*Array.Clear
===List<<T>>===
=====インデクサを備える=====
*サイズ可変の配列のようにふるまう
**配列 T[] を期待しているパラメータに List<<T>>は渡せない**IList<<T> > を期待しているパラメータには、配列もList<<T>>も渡すことができる
=====初期化子=====
*var nums = new List<<int> > { 1,2,3 };
===リストインターフェースとシーケンスインターフェース===
=====.NET Frameworkのコレクションインターフェース=====
*IList<<T>>**ICollection<<T>>,IEnumrable<<T> > も実装する必要がある**List<<T>>,配列 は IList<<T> > を実装している*ICollection<<T>>
**変更可能なコレクションに対する汎用インターフェース
**実装時には、IEnumerable<<T> > も提供する必要がある*IEnumerable<<T>>
**実装者に対する要求が最も少ない
**列挙子を返す
**LINQ to Objects の核心を占める
<<blockquote>>IEnumerable<<T>>を実装し、GetEnumeratorメソッドを定義するとクラスそのものを列挙可能にできる<</blockquote>>
====リストとシーケンスを実装する====
*IEnumerable<<T> > または、IList<<T> > のどちらかの形式で情報を提供すると便利なことが多い*LINQ to Objects が提供する演算はすべて IEnumerable<<T>>で動く
===イテレータ===
*yield を使って列挙可能なシーケンスを生成
*IEnumerable<<T> > を実装する言語サポート public static IEnumerable<<int> > Numbers(int start, int count) { for (int i=0; i<<count; i++) {
yield return start + i;
}
}
}
===Collection<<T>>===*List<<T> > にと似ているがAPIがずっと小さい
*リストが分かる方法を提供
*IList,IList<<T>>を実装===ReadOnlyCollection<<T>>===
*変更不要なコレクションを提供
*リストのラッパーとして利用できる
===ディクショナリ===
=====Dictionay<<TKey,TValue>>=====*IDictionay<<TKey,TValue> > インターフェースを実装
=====TryGetValue=====
*データをディクショナリから探す
====初期化====
*IEnumerable<<KeyValuePair<<TKey,TValue>>>>
=====コレクション初期化構文を利用できる=====
var dic = new Dictionary<<string,int> > {
{"One",1},
{"Two",2}
=====インデックス初期化子=====
*C#6から下記の初期化記法が追加されているこちらを推奨
var dic = new Dictionary<<string,int> > {
["One"] = 1,
["Two"] = 2
*大文字小文字を区別しないディクショナリ
var dic = new Dictionary<<string, int>>(StringComparer.InvariantCultureIgnoreCase);
=====ソート済みディクショナリ=====
*SortedDictionary<<TKey,TValue>>*SortedList<<TKey,TValue>>
===集合===
=====ISet<<T>>=====
*実装
**HashSet<<T>>**SortedSet<<T>>
===キューとスタック===
=====Queue<<T>>==========Stack<<T>>=====
===リンクリスト===
=====LinkedList<<T>>=====
=====利点=====
*要素の挿入削除が安価
===並行コレクション===
=====並行プログラミングの課題を解くよう設計=====
*ConcurrentQueue<<T>>*ConcurrentStack<<T>>*ConcurrentDictionary<<TKey,TValue>>*ConcurrentBag<<T>>*BlockingCollection<<T>>
===タプル===
*固定個数の要素を含むデータ構造
*各要素は異なる型でもよい
*8つの型引数を取る8タプルまで準備されている
Tuple<<T1,T2>>
*Item1,Item2 など読み取り専用プロパティで内容にアクセス
var four = Tuple.Create(1,"One",new[] {1,2}, 3.4);
int max = initial;
int min = max;
nums.ToList().ForEach(x => > { max = (x > > max) ? x : max; min = (x < < min) ? x : min; });
return (max, min);
}
=====ジェネリッククラスから派生させる場合、型引数を渡さなければならない=====
*派生クラスがジェネリックではない
**public class NonGenericDerived : GenericBase<<string> > {}
**具体的な型を渡す
*派生クラスがジェネリック
**public class GenericDerived<<T> > : GenericBase<<T> > {}
**自身の型パラメータを渡す
*組み合わせ
**public MixedDerived<<T> > : GenericBase2<<string, T> > {}
**複数の型パラメータがある場合、2つの手法を組み合わせられる
=====共変性と反変性=====
*共変性(covariance)
**共変性型パラメータ
**--public interface IEnumrable<<out T> > : IEnumrable
**.NET Framework 4 以降には、共変の型パラメーターを持つジェネリック インターフェイス
**--IEnumerable<<T>>、IEnumerator<<T>>、IQueryable<<T>>、IGrouping<<TKey, TElement> >
**--すべての型パラメーターは共変のみであるため、型パラメーターはメンバーの戻り値の型だけに使用
*反変性(contravariance)
**反変性型パラメータ
**--public interface ICompara<<in T>>
**.NET Framework 4 以降には、反変の型パラメーターを持つジェネリック インターフェイス
**--IComparer<<T>>、IComparable<<T>>、IEqualityComparer<<T> > など
**--型パラメーターは反変のみであるため、これらの型パラメーターは、インターフェイスのメンバーのパラメーター型としてのみ使用
*数学の圏論(category theory) から来ている
*public new void SomeMethod() {}
*newキーワードで明示しコンパイラ警告を抑制
<<blockquote>>プロパティにも適用される<</blockquote>>
<<blockquote>>オーバーライドは、virtual/override のセットが前提だが、隠蔽は、派生クラスでnewするだけで利用可能。ただし、隠蔽ではポリモーフィズムは動作しない。<</blockquote>>
===sealedメソッドとクラス===
*sealed メソッドは virtual の逆でオーバーライドができないようにシールする
*GCは弱参照を追跡しない
*オブジェクトが弱参照からしか到達できないなら、GCはそれが到達不能なオブジェクトであるかのように扱う
*WeakReference<<T>>
=====メモリの回収=====
*CLRはヒープを世代で管理
**------複数の論理プロセッサ時デフォルト
**------意図的に無視したい場合
**--------<<gcConcurrent enabled="fales”/>>
**------GC間でのスレッドの停止時間を最小限に抑える
**------GCが発生している間でも、コードが実行し続けられるようにすることが目的
**----web.config
**----App.config
<<runteme>> <<gcServer enabled="true">> <</runtime>>
**--論理プロセッサが複数ある場合にのみ利用可能
**--スループットはワークステーションより優れる
=====オブジェクト変数はヒープ上のものの参照を保持するだけ=====
=====概念=====
public class Box<<T> > where T : struct {
public readonly T Value;
public Box(T v) {
=====object 型に box 化された int を取り出すのに、(int)o と書ける=====
=====組み込みの値型だけではなく、すべての構造体に対して自動的に利用できる=====
=====Nullable<<T> > のボックス化=====*Nullable<<int> > の代わりに、int? と書ける
*すべて成功
object boxed = 42;
*C#7以降では、式としてthrowを利用できる
=====条件演算子=====
*i < < 0 なら例外 Console.WriteLine(i >>= 0 ? i : throw new Exception("minus"));
=====null合体演算子=====
*strがnulllなら例外
=====式形式のラムダ式/メソッド=====
*例外をスローするだけ
void Hoge() => > throw new NotSupportedException("not implemented");
====例外を再スロー====
*間違った例
*NotSupportedException
**インターフェースが要求したときにスロー
**例えばIList<<T> > はコレクションを変更するメソッドを定義しているが、コレクションが変更可能である必要はない
**読み取り専用の場合、変更するメンバからスローする
===カスタム例外===
===デリゲート型===
====デリゲートパラメータを持つメソッド====
*public static int FindIndex<<T> > (T[] arry, Predicate<<T> > match)
*predicate(述語、プレディケート)
**あるものが真か偽を判断する機能
**Predicate<<T>>デリゲート型 public delegate bool Predicate<<T>>(T obj)
====アクセシビリティ====
*他の型同様
**--bool Hoge(object o)
**----いずれとも互換
**------Predicate<<object>>**------Predicate<<string>>
====生成====
=====new キーワード=====
*通常コンストラクタへの引数を渡す個所に互換性を持つメソッドの名前を指定できる
var p = new Predicate<<int>>(IsGreaterThanZero);
*実際には new をデリゲートに使用することはほとんどない
*コンパイラが推論できない場合のみ
=====暗黙的作成=====
Predicate<<int> > p =IsGreaterThanZero;
*他のクラスのメソッドへのデリゲート
Predicate<<int> > p = OtherClz.IsGreaterThanZero;
*インスタンスメソッドも参照できる
*スコープ内で名前によって参照
*戻り値は最後に実行されたメソッドのものが返される
*実際はCombineメソッドではなく、「+」「+=」 を利用
Predicate<<int> > p = gereaterThanZero;
p += greaterThanTen;
p +=greaterThanOneHundred;
====呼び出し====
*メソッドパラメータ、プロパティとして使うことも可能
public static int Hoge(Predicate<<int> > userCallback) {
return userCallback(42);
}
**------戻り値 void
public delegate void Action();
public delegate void Action<<in T1>>(T1 arg1); public delegate void Action<<in T1, in T2>>(T1 arg1, T2 arg2);
:
**----Func
**------Actionとよく似るが、戻り値を返す
public delegate TResult Func<<out TResult>>(); public delegate TResult Func<<in T1, out TResult>>(T1 arg1); public delegate TResult Func<<in T1, in T2, out TResult>>(T1 arg1, T2 arg2);
:
**--ほとんどは特殊化されている
*共変性
**共変 (covariant): 広い型(例:double)から狭い型(例:float)へ変換
Predicate<<object> > po =IsLongString; Predicate<<string> > ps = po;
*不変性
**不変 (invariant): 型を変換できないこと。
|}
===ラムダ式===
*delegateキーワードは書かずに、=> > で引数とメソッド本体とをつなぐ int idx = Array.FindIndex(ary, x => > x == 5);
====バリエーション====
*本体が1文の場合、ブロック {} を省略可能
*引数が1つの場合、引数の括弧も省略可能
*引数がない場合の括弧は省略できない
Predicate<<int> > p1 = value => > value > > 0; Predicate<<int> > p2 = (value) => > value > > 0; Predicate<<int> > p3 = (int value) => > value > > 0; Predicate<<int> > p4 = value => > { return value > > 0; }; Predicate<<int> > p5 = (value) => > { return value > > 0;}; Predicate<<int> > p6 = (int value) => > { return value > > 0;};
*引数のないラムダ
Func<<bool> > isAfternoon = () => > DateTime.Now.Hour >>= 12;
====キャプチャされた変数====
*インラインメソッドからその外側のメソッドの変数参照ができる
public static Predicate<<int> > IsGreaterThan(int threshold) { return value => > value > > threshold;
}
Predicate<<int> > greaterThanTen = IsGreaterThan(10);
bool result = greaterThanThen(200);
====ラムダと式ツリー====
*他にも隠れた機能
*データ構造を作成できる
*Expression<<T>>
*Tはデリゲート型
*Expression 自体はデリゲートではない
*Entity Framework
var expensiveProducts = dbCOntext.Products.Where(p => > p.ListPrice > > 3000);
*SQLクエリを生成
WHERE [Extent1].[ListPrice] > > cast(3000 as decimal(18))
====ラムダ式を伴うListクラスのメソッド====
*Listクラスでは、引数に対してラムダ式を指定できるメソッドが多く用意されている。
*宣言
public class Eventful {
public event Action<<string> > Announcement;
public void Announce(string message) {
if (Announcement != null) {
*扱い
var souce = new Eventful();
source.Annoucement += m => > Console.WriteLine("msg:" + m);
=====標準的なイベントデリゲートパターン=====
*最もシンプルで広く利用
**ハンドラを削除する必要がある場合
**--イベントは最良の選択肢
**高度な機能を必要とする場合、IObsevable<<T> > が最良の選択肢となる
**ターゲットメソッドが1つだけであることが明白
**--メソッドまたはコンストラクタへの引数としてデリゲートを渡すのが一般的