白猫のメモ帳

C#とかJavaとかJavaScriptとかHTMLとか機械学習とか。

Java使いがC#を勉強する その① データ型

こんばんは。

今日は節分ですね。
恵方巻き食べましたか?豆まきしましたか?
私はこれからまきます…。

さて、C#の言語仕様をJavaと比較してみるシリーズ始めます。
最初はデータ型について比較してみましょう。

値型(プリミティブ型)


C# Java 説明
sbyte byte 整数値 (符号つき)
byte - 整数値 (符号なし)
short short 整数値 (符号つき)
ushort - 整数値 (符号なし)
int int 整数値 (符号つき)
uint - 整数値 (符号なし)
long long 整数値 (符号つき)
ulong - 整数値 (符号なし)
float float 浮動小数点数
double double 浮動小数点数
char char 文字値
bool boolean 真偽値
decimal - 10進数値
enum enum 列挙型
struct - ユーザー定義の構造体


符号つきと符号なしを区別していたりと、C#の方が数が多いです。
注意なのが「byte」と「sbyte」で、Javaでの「byte」はC#では「sbyte」になります。

「bool」と「boolean」は単純に名前が違うので面倒ですね。

「decimal」はJavaでいうところの「BigDecimal」と思っていいんでしょうか。
浮動小数点数値ではないので、精度の必要な計算ではこれを使うことになりそうですね。

参照型


いわゆるクラスなので無限にあるわけですが、
C#では以下の2つが少し特殊で、参照型にもかかわらずパスカル記法ではありません。

・object → Objectのエイリアス
・string → Stringのエイリアス

実は「int」(System.Int32)などもエイリアスなわけですが、
値型が構造体なのに対して、「Object」と「String」はクラスです。(構造体については次の項目で)

はて、よく使うから?

構造体


C#には構造体(struct)という仕組みがあります。
基本的にはクラス似ていますが、値型として扱われるのがポイントです。

Javaでもプリミティブは値渡し、オブジェクトは参照渡しなので、その感覚で問題なさそうです。
値のコピーと参照のコピーのメモリコストの分岐点は16バイトらしいですね。

クラスとの違いは、

・パラメーターなしのコンストラクタを定義できない
インスタンスフィールドは初期化できない
・new演算子を使用せずにインスタンス化できる
・継承できない(継承元にもなれない、インタフェースの実装はできる)

といったところです。

public class Hoge
{
  public int Huga { get; set; }
}

public struct Hoge
{
  public int Huga { get; set; }
}

さらっとプロパティ出てきてますけどスルーでお願いします。

Hoge hoge1 = new Hoge();
hoge1.Huga = 1;

Hoge hoge2 = hoge1;
hoge2.Huga = 2;

例えば、Hogeがクラスの場合には参照がコピーされているので、hoge1.Hugaは2ですが、
Hogeが構造体の場合には値がコピーされているので、hoge1.Hugaは1になりますね。

varとdynamic


JavaにはないC#の型に「var」と「dynamic」があります。(型なのでしょうか…?)

「var」は暗黙の型です。
書いてないけどわかるでしょ?くらいな感じで、型チェックされます。
なので、IDEでもちゃんと補完が効きます。

var hoge = "abc";
hoge = hoge.Replace('b', 'B');

var fuga = 10;
fuga = fuga.Replace('b', 'B');  // コンパイルエラーになる


一方で「dynamic」はコンパイル時の型チェックをバイパスします。
当然、IDEでの補完は効きません。

dynamic hoge = "abc";
hoge = hoge.Replace('b', 'B');

dynamic fuga = 10;
fuga = fuga.Replace('b', 'B');  // 実行時エラーになる

 

あ、結構違う…


似たような顔しているかと思ったけど、すでに結構違うじゃないですか。
うわーん。