前回の復習
変数の命名規則から型の種類, リテラルと渡って今回.
二章を終わらせて演算子の章へと入っていく.
§2 C#の基本(つづき
2.4 型変換
暗黙な型変換と明示的な型変換(キャスト)がするみたい
暗黙的な変換
数値リテラルにおいては暗黙てな型変換が対応している様子.
暗黙的変換の対応表はこちら
ほか言語にもあるように, 浮動小数点<->整数の間で情報落ちももちろん発生する.
int i = 16777216;
float f = i;
Console.WriteLine(f) // result: 1.677721'2'e07 情報落ちが発生している
明示的な変換(キャスト)
暗黙てな変換は別称で"拡大解釈"といわれるらしい.
扱える値のキャパが狭い型から広いキャパに対して変換をするからだとか
対して明示的な変換は縮小変換...というのだとか. これは, キャパが広い物から狭い物への変換.
明示的型変換対応表
(データ型) 変数
で行えるみたい
int i = 13;
byte b=(byte)i;
ちなみに, 本では変数と書いてあったけどダイレクトに値を指定してあげてもできた. (byte)123みたいなのでも可能みたい.
前回, サフィックスを扱ったけれどこっちの方が見やすい気がする...
開発者が値の範囲を保障する必要があるので注意が必要
2.4.3 文字列と数値の変換
数値型のクラスからParseメソッドを使う.
10進数以外の進数を扱う場合は例外的な扱いが必要.
逆に数値を文字列にする場合は, 数値型のToStringメソッドを使用する
Int32.Parse("108));
Single.Parse("3.14"); // float
Int32.Parse("FF", System.Globalization.NumberStyles.HexNumber); // 16進数, 0xはいらない
Convert.ToInt32("11", 2) // 11を二進数に
int i = 123;
123.ToString();
i.ToString();
調べてみると, Conver.ToXXXの第二引数は2進数以外にも任意の進数にできるみたい.
2.5 参照型
参照型を分類すると
- クラス型(include string, object)
- インターフェース型
- デリゲート型
- 配列型
ここではclass, array, 補足としてnullを扱う
2.5.1 クラス型
オブジェクト指向の説明は割愛.
クラスに用意されたデータの入れ物のことをフィールド, それを操作するための関数をメソッド, というらしい.
フィールドとはプロパティの事かなと思って調べてみるとどうも違うらしい.
フィールドはカプセル化されたデータのこと, プロパティはフィールドのsetterとgetter...みたいなことかな?
データメンバー, 関数メンバーのそれぞれの代表例がフィールド, メソッドという認識にして先へ進む.
インスタンス化とメンバーの呼び出し
インスタンスとはオブジェクトをかっこつけた言い方...ってどっかのイベントで言われたというのを風のうわさで聞いた.
デザインパターンの勉強もいずれしたいな
インスタンス化ではクラスを複製してメモリを確保する, と書いてある.
ただし, 確保されるのはフィールド用のメモリ(メソッドはオブジェクトがここに持つ必要がないから
クラスをインスタンス化するにnew
を用いる.
メンバに対するアクセスは"."の後にフィールド名もしくはメソッド名を入れる
//class name = new class(args)
FileInfo f = new FileInfo(@"c:\data");
// obj.field [= val]
// obj.method(args)
var nospace = "asdf asdf".Trim();
クラスメソッド/フィールド
クラスに対して静的なフィールド, メソッドの呼び出し.
// Class.field [= val]
// Class.method(args)
Console.WriteLine("asdf");
null
nullってわりと怖いイメージ. nilが存在してたり何かと敬遠したくなる.
よくトイレットペーパーでundefined, null, 0を表すやつを思い出した.
参照型はallocしただけの場合, nullが初期値になる. また, 値として参照型にnullを入れることも可能.
ただし, nullの場合はフィールド, メソッドにアクセスすると, NullReferenceExceptionが発生する.
string str = null;
string unspace = str.Trim(); // NullReferenceException Error
null参照エラーを極力避けるためにも, 初期値は入れておいたほうが良いと確かほんの最初の方にも書いてあった.
実際, pythonやJuliaで配列生成するときも, zeros(n,m)とかうつし, C#でもそれは同じなのだろう.
null条件演算子
objが非nullならばアクセスしたい, それ以外ならnullを返したい, という場合, null条件演算子(?.
)を用いることでそれが可能らしい.
string str = null;
string unspace = str?.Trim(); // return null
これは, 値の存在確認ができるということと同じなのかな(c.f. XX==null, はc#ではできる様子)
Nullable 型
標準的な参照型じゃない値型の物では, "どの値をも参照してない"意味のnullは使えないが, それを可能にする型
有効な値と, 値として無効な状態を区別するために使う様子. minimumを設定することで表してた時代もあったとか
type?
というように, typeの後に?を付けることでできる様子
int num = 108;
int? num3 = null;
全てが参照型の言語を使っていた自分からすると珍しい記法だ
プロパティとして, HasValue(値保持の確認), Value(値を戻す)の二つを持つ
ちなみに
- ?を付けずにnullを代入すると型変換できませんでした, とでる
- string? = XXX, はエラーを吐く
- type?は, 実はNullableのシンタックスシュガーらしい. ジェネリックだ
Nullableの変換
暗黙的/明示的と同じルール.
nullを扱えるという点で広いキャパを持つtype?からtypeへはキャストが必要, 逆はいわゆる"拡大解釈"
int i = 108;
int? num = i;
int honya = (int)num;
ただし個人的には, 上記のnumに対して, num.Valueとした方が同じキャパなのであれば楽に見える....
2.5.3 配列
勝手にC#の配列はコレクションだと思っていましたが普通に配列もあったのか....
宣言
- サイズで宣言:
type[] name = new type[number of elements]
- 初期値を指定:
type[] name = { e1, e2, e3...}
] - var を用いる:
var name = new[] { e1, e2...}
// 自動的に型は判別される
初期値指定の方法では, 要素の列挙は複数行にわたっていても ", " で行が区切られている限りokらしい.
また, 初期値を指定する宣言方法の時, 宣言と初期化を分けるのであれば
int[] data;
data = new[]{1,2,3,4,5};
という形で, new[]の記述が必要になる様子
アクセス
ほか言語と同じ.
data[n] | nは任意の要素番号(0始まり)
要素の書き換えも同様に可能だけれど, out of rangeの例外投げられないようにね
多次元配列
type[,] name = new type[num of row, num of column]
type[,] name = new[,] { {e1,e2,e3}, {e4,e5,e6} }
ブラケットに","を入れる. 上記は行列になるけれど, テンソルなど作る場合は[,,]となるみたい.
アクセスにしても, ブラケットを分けて記述せずに, d[m,n]という風に書く
ジャグ配列
行列としてではなくて, aryを格納するためのaryのようなaryを作ろうとすると, ジャギーな配列, ジャグ配列を作りたくなる場合もある.
宣言方法
// dtype[][] name = new dtype[num of e][]
// name[index] = new dtype[num of e]
int[][] data = new int[3][]; //3つのary格納
data[0] = new int[2];
data[1] = new int[3];
data[2] = new int[4];
初期値を与えたかった場合は, new[]{a,b,c}という風にも書ける.
配列のサイズと次元数を求める.
Length/Rank propertyを利用.
ただし
- 多次元配列の場合は, 配列内すべての要素の数を返す
- ジャグ配列の場合は, 何個の配列を扱っているかを返す
ジャグ配列は多次元に見えるけれど, 配列を格納している一次元配列の扱いのようだ
次回から三章, 演算子に入ります.