C Sharpとは?

C Sharp

出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2017/09/18 17:48 UTC 版)

本来の表記は「C#」です。この記事に付けられた題名は、技術的な制限により、記事名の制約から不正確なものとなっています。
C#
C#のロゴマーク。テキスト上では#と代替表記されるが、正式には♯と描く。
パラダイム 構造化, 命令型, オブジェクト指向, 関数型, イベント駆動型, ジェネリック, リフレクション, 並行計算
登場時期 2000年 (2000)
設計者 マイクロソフトアンダース・ヘルスバーグ率いるチーム)
開発者 マイクロソフト
最新リリース 7.0 / 2017年3月7日(6か月前) (2017-03-07
型付け 強い静的型付け(4.0から動的型導入)
主な処理系 CLR, Mono
方言 1.0, 1.5, 2.0 (ECMA), 3.0, 3.5, 4.0, 5.0, 6.0, 7.0
影響を受けた言語 C++, Delphi, Eiffel, Java, LISP
影響を与えた言語 D言語, F#, Java, Nemerle, Vala
プラットフォーム Windows, macOS, Linuxなど
ライセンス Apacheライセンス (Roslyn)
ウェブサイト www.visualstudio.com

C#(シーシャープ)とは、マイクロソフトが開発したマルチパラダイムプログラミング言語。強い型付け命令型宣言型手続き型関数型ジェネリックオブジェクト指向の要素を持つ。

マイクロソフトのソフトウェアフレームワークである.NET Frameworkとともに作られ、Ecma International[1]および国際標準化機構 (ISO)[2] によって標準化されており、日本においても日本工業規格 (JIS)[3]によって採択された。

概要

開発にはボーランド社のTurbo PascalDelphiを開発したアンダース・ヘルスバーグを筆頭に多数のDelphi開発陣が参加している。

C#は共通言語基盤共通言語ランタイムなど)が解釈する共通中間言語コンパイルされて実行される。基本的な書式がC言語風になっているため、初見の構文はサン・マイクロシステムズ社によるJavaに近いと言われるが、実際の構文はDelphiに準じており、C言語風ということもありC++ Builderの独自拡張構文に極めて近い内容となっている。またプロパティデリゲートなどDelphiの構文そのまま、もしくは名称変更しただけの機能となっているものが多い。

自動ボックス化デリゲートプロパティインデクサカスタム属性ポインタ演算操作、構造体(値型オブジェクト)、多次元配列可変長引数、などの機能を持つ。また、Javaと同様に大規模ライブラリプロセッサ・アーキテクチャに依存しない実行形態、ガベージコレクションJITコンパイルによる実行の高速化、などが実現されている(もっともこれらはC#の機能というより.NET Frameworkによるものである)。

.NET構想における中心的な開発言語であり、XML WebサービスASP.NETの記述にも使用される。他の.NET系の言語でも記述可能だが、生産性・機能においてC#が最も優れるとされる。マイクロソフトの統合開発環境では、Microsoft Visual C#がC#に対応している。

共通言語仕様のCLSによって、他のCLS準拠の言語(Visual Basic .NETVisual C++ (C++/CLI)など)と相互に連携することができる。他言語で記述されたクラス継承することも、またその逆も可能である。

リリース時期

  • 1.0  2002年4月
  • 1.1  2003年5月
  • 2.0  2005年12月
  • 3.0  2007年12月
  • 4.0  2010年4月
  • 5.0  2012年8月
  • 6.0  2015年7月
  • 7.0  2017年3月

言語仕様

さまざまな意味において、基盤であるCLIの機能をもっとも反映している言語であるといえる。C#にある組み込み型のほとんどは、CLIフレームワークに実装されている値型と対応している。しかし、C#の言語仕様はコンパイラのコード生成については何も言及していない。つまり、CLRに対応しなければならないとか、共通中間言語 (CIL) などの特定のフォーマットのコードを生成しなければならないとかいうことは述べられていない。そのため、理論的にはC++FORTRANのように環境依存のマシン語を生成することも可能である。しかし、現在存在するすべてのC#コンパイラはCLIをターゲットにしている。

CやC++からの改良点

C#では、CやC++と比較してさまざまな制限や改良が加えられている。その例を次に挙げる。

  • グローバル変数やグローバルメソッドは存在しない。すべてのメソッドとメンバはクラスの一部として宣言されなければならない。
  • 外のブロックで宣言した変数名を、内のブロックで再宣言してはいけない。これはC++ではしばしば混乱や曖昧のもととされているが、C#では禁止されている。
  • Cのprintf()関数のように関数をグローバルで公開するのではなく、すべての関数はクラス内で宣言されなければならない。ほとんどの場合クラスは名前の衝突を避けるために名前空間に所属する。
  • 名前空間は階層構造をもつ。つまり、名前空間は他の名前空間の中に宣言することができる。
  • 原始型を含めたすべての型は、objectクラスの派生クラスである。つまりobjectクラスのもつすべてのプロパティやメソッドを継承する。例えば、すべての型はToString()メソッドをもつ。
  • C#にはブール型boolが存在する。whileifのように条件をとるステートメントには、bool型の式を与えなければならない。CやC++にもブール型が存在するが、これは整数型と相互に変換可能で、while文やif文に与える式として整数やポインタも許容していた。C#ではミスを防止するために、このブール型と整数が可換であるという仕様を禁止している。
  • ポインタをサポートする。ポインタはunsafeスコープ内のみで使用することができ、適切な権限をもつプログラムのみがunsafeとマークされたコードを実行することができる。オブジェクトへのアクセスの大部分は管理された安全な参照によってなされ、大部分の算術演算はオーバフローのチェックがなされる。unsafeポインタは値型や文字列を指すことができる。セーフコードでは、必ずしもそうする必要はないものの、IntPtr型を通してポインタをやりとりすることができる。
  • マネージドなメモリを明示的に解放する方法は存在せず、参照されなくなったメモリはガベージコレクタによって自動的に解放される。ガベージコレクタは、メモリの解放忘れによって起こるメモリリークを解消する。C#は、データベース接続のようなアンマネージドなリソースに対しても明示的に制御する方法を提供している。これはIDisposableインタフェースとusingステートメントによってなされる。
  • クラスは複数のインタフェースを実装することができるが、多重継承はサポートされない。
  • C#はC++に比べて型安全である。既定の暗黙変換は、整数の範囲を広げる変換や、派生クラスから基底クラスへの変換といった、安全な変換のみに限定される。これは、コンパイル時、JITコンパイル時、そして一部の動的なケースでは実行時に強制される。ブール型と整数型、列挙型と整数型、の間は暗黙変換はできない。暗黙変換をユーザ定義する際は、明示的にそのように指定しなければならない。これはC++のコンストラクタとは違った仕様である。
  • 列挙型のメンバは、列挙型の名前空間の中におかれる。また、列挙型の定数名を取得することができる。さらに、列挙型の定数名から動的に定数値を得ることができる。
  • プロパティと呼ばれるアクセサは、C++におけるメンバフィールドのような構文でオブジェクトにアクセスすることができる。C++では、publicとしてメンバを宣言することでメンバを読むことも変更することもできるようになるが、C#ではプロパティによってメンバアクセスやデータの正当性チェックを制御することができる。
  • switch文で、基本型のみならず、定数文字列によって分岐することができる。

C# 2.0からの仕様

部分型

部分型 (Partial Type) が導入された。以下のようにクラスや構造体の宣言にpartial修飾子をつけることで、その宣言を分割することができる。

partial class MyClass { int a; }
partial class MyClass { int b; }

これは以下と同義である:

class MyClass { int a; int b; }

これによって、巨大なクラスを分割したり、自動生成されたコードを分離したりすることができる。partial 修飾子はすべての宣言につける必要がある。

ジェネリクス

ジェネリクスが導入された。これは.NET Framework 2.0の機能である。クラス、構造体、インタフェース、デリゲート、メソッドに対して適用することができる。.NETのGenericsはC++のテンプレート、あるいはJavaにおけるそれとも異なるもので、コンパイルによってではなく実行時にランタイムによって特殊化される。これによって異なる言語間の運用を可能にし、リフレクションによって型パラメタに関する情報を取得することができる。また、where節によって型パラメタに制約を与えることができる。一方、C++のように型パラメタとしてを指定することはできない。なお、ジェネリックメソッドの呼び出し時に引数によって型パラメタが推論できる場合、型パラメタの指定は省略できる。

静的クラス

静的クラスが導入された。static属性をクラスの宣言につけることで、クラスはインスタンス化できなくなり、静的なメンバしか持つことができなくなる。

yieldキーワード

yieldキーワードによるコルーチンを使うことで、イテレータを楽に実装できるようになった。

匿名デリゲート

クロージャの機能を提供する匿名デリゲートが導入された。

プロパティに対する個別のアクセス制御

プロパティのget もしくは setアクセサのどちらかにアクセス修飾子を指定することでアクセス制御が別個にできるようになった。次の例では、getアクセサはpublicsetアクセサはprivateである。

public class MyClass
{
  private string status = string.Empty;
  public string Status
  {
    get { return status; }
    private set { status = value; }
  }
}

Null許容型とnull結合演算子

nullを保持できる値型、Nullableが導入された。

int? i = 512;
i = null;

int? j = i + 500; //jはnullとなる。nullとの演算の結果はnullになる。

int?Nullable<int>糖衣構文である。また、nullを保持しているNull許容型のインスタンスをボックス化しようとすると、単に空参照 (null) に変換される[4]

int? x = null;
object o = x;
System.Console.WriteLine(o == null); //Trueが出力される

また、null結合演算子 (??)が導入された。これは、nullでない最初の値を返す。

object obj1 = null;
object obj2 = new object();
object obj3 = new object();
return obj1 ?? obj2 ?? obj3; // obj2 を返す

この演算子は主にNullable型を非Nullable型に代入するときに使われる。

int? i = null;
int j = i ?? -1; // nullをint型に代入することはできない

C# 3.0からの仕様

varキーワード

var キーワードが導入され、型推論を利用したローカル変数の宣言ができるようになった。

var s = "foo";
// 上の文は右辺が string 型であるため、次のように解釈される:
string s = "foo";
// 以下に挙げる文は誤りである(コンパイルエラーとなる):
var v; // 初期化式を欠いている (型を推論する対象が存在しない)
var v = null; // 型が推論できない (曖昧である)

拡張メソッド

拡張メソッドが導入された。既存のクラスを継承して新たなクラスを定義することなく新たなインスタンスメソッドを追加定義することができる。具体的には、独自の静的クラス内に this 修飾子をつけた、拡張メソッドを追加する対象の型の引数を最初に持つメソッドを定義することによって、通常の静的メソッドとしての呼び出しの他に指定した型のインスタンスメソッドとしての呼び出しを行うことができるメソッドを作ることができる。以下に例を挙げる:

public static class StringUtil
{
  public static string Repeat(this string str, int count)
  {
    var array = new string[count];
    for (var i = 0; i < count; ++i) array[i] = str;
    return string.Concat(array);
  }
}

この例は string 型に、文字列 (string 型のインスタンス)を指定した回数繰り返したものを返すメソッド Repeat を追加している。このメソッドは、以下のように呼び出すことができる:

// 静的メソッドとしての呼び出し
StringUtil.Repeat("foo", 4);
// 拡張メソッドとしての呼び出し
"foo".Repeat(4);
// (どちらの例も "foofoofoofoo" を返す)

また、列挙型やインターフェースなど本来メソッドの実装を持ち得ない型に、見かけ上インスタンスメソッドを追加することも可能である。以下に例を挙げる:

public enum Way
{
  None, Left, Right, Up, Down
}

public static EnumUtil
{
  public static Way Reverse(this Way src)
  {
    switch(src)
    {
      case Way.Left:  return Way.Right;
      case Way.Right: return Way.Left;
      case Way.Up:    return Way.Down;
      case Way.Down:  return Way.Up;
      default : return Way.None;
    }
  }
}

このメソッドは以下のように呼び出すことができる:

Way l = Way.Left;
Way r = l.Reverse(); // Way.Right

部分メソッド

部分メソッドが導入された。部分型(partial 型)内で定義された private で、かつ戻り値が void のメソッドに partial 修飾子をつけることでメソッドの宣言と定義を分離させることができる。定義されていない部分メソッドは何も行わず、何らエラーを発生させることもない。例えば:

partial class Class
{
  partial void DebugOutput(string message);
  
  void Method()
  {
    DebugOutput("Some message");
    Console.WriteLine("Did something.");
  }
}

上のコードにおいて Method() を呼び出すと、Did something. と表示されるだけだが、ここで以下のコード:

partial class Class
{
  partial void DebugOutput(string message)
  {
    Console.Write("[DEBUG: {0}] ", message);
  }
}

を追加した上で Method() を呼び出すと、[DEBUG: Some message] Did something. と表示される。

ラムダ式

匿名メソッドをより簡略化した記法として、ラムダ式が導入された。この名前はラムダ計算に由来する。

以下の匿名メソッド

// iを変数としてi+1を返すメソッド
delegate (int i) { return i + 1; }

は、ラムダ式を使って次のように記述できる:

(int i) => i + 1; /* 式形式のラムダ */
//或いは:
(int i) => { return i + 1; }; /* ステートメント形式のラムダ */

ラムダ式は匿名メソッドと同様に扱えるが、式形式のラムダがExpression<TDelegate>型として扱われた場合のみ匿名メソッドとして扱われず、コンパイラによって式木を構築するコードに変換される。匿名デリゲートが実行前にコンパイルされたCILを保持するのに対し、式木はCILに実行時コンパイル可能であるDOMのような式の木構造そのものを保持する。これはLINQクエリをSQLクエリなどに変換する際に役立つ。

以下は、3つの任意の名前の変数、整数、括弧、及び四則演算子のみで構成された式を逆ポーランド記法に変換する汎用的なコードである:

public static string ToRPN(Expression<Func<int, int, int, int>> expression)
{
  return Parse((BinaryExpression) expression.Body).TrimEnd(' ');
}

private static string Parse(BinaryExpression expr)
{
  string str = "";
  
  if (expr.Left is BinaryExpression)
  {
    str += Parse((BinaryExpression) expr.Left);
  }
  else if (expr.Left is ParameterExpression)
  {
    str += ((ParameterExpression) expr.Left).Name + " ";
  }
  else if (expr.Left is ConstantExpression)
  {
    str += ((ConstantExpression) expr.Left).Value + " ";
  }

  if (expr.Right is BinaryExpression)
  {
    str += Parse((BinaryExpression) expr.Right);
  }
  else if (expr.Right is ParameterExpression)
  {
    str += ((ParameterExpression) expr.Right).Name + " ";
  }
  else if (expr.Right is ConstantExpression)
  {
    str += ((ConstantExpression) expr.Right).Value + " ";
  }
  
  return str + expr.NodeType.ToString()
    .Replace("Add", "+")
    .Replace("Subtract", "-")
    .Replace("Multiply", "*")
    .Replace("Divide", "/")
    + " ";
}

// 呼び出し例:
ToRPN((x, y, z) => (x + 1) * ((y - 2) / z)); // "x 1 + y 2 - z / *" を返す

オブジェクト初期化の簡略化

オブジェクトの初期化が式として簡潔に記述できるようになった。

var p = new Point { X = 640, Y = 480 };
// 上の文は次のように解釈される:
Point __p = new Point();
__p.X = 640;
__p.Y = 480;
Point p = __p;

また、コレクションの初期化も同様に簡潔に記述できるようになった。

var l = new List<int> {1, 2, 3};
var d = new Dictionary<string, int> {{"a", 1}, {"b", 2}, {"c", 3}};
// 上の文は次のように解釈される:
List<int> __l = new List<int>();
__l.Add(1);
__l.Add(2);
__l.Add(3);
List<int> l = __l;
Dictionary<string, int> __d = new Dictionary<string, int>();
__d.Add("a", 1);
__d.Add("b", 2);
__d.Add("c", 3);
Dictionary<string, int> d = __d;

但し、上のコードでは匿名の変数に便宜的に __p、__l、__d と命名している。実際はプログラマはこの変数にアクセスすることはできない。

自動実装プロパティ

プロパティをより簡潔に記述するための自動実装プロパティが導入された。プロパティの定義に get; set; と記述することで、プロパティの値を保持するための匿名のフィールド(プログラマは直接参照することはできない)と、そのフィールドにアクセスするためのアクセサが暗黙に定義される。また、C# 5.0 までは get;set;のどちらか片方だけを記述することは出来なかったが、C# 6.0 からは get; のみが可能。以下のコード:

public int Value { get; set; }

は、以下のようなコードに相当する動作をする:

private int __value;
public int Value
{
  get { return __value; }
  set { __value = value; }
}

但し、上のコードでは匿名のフィールドに便宜的に __value と命名している。実際はプログラマはこのフィールドにアクセスすることはできない。

匿名型

一時的に使用される型を簡単に定義するための匿名型が導入された。以下に例を挙げる:

new { Name = "John Doe", Age = 20 }

上の式は、以下の内容のクラスを暗黙に定義する。定義されたクラスは匿名であるが故にプログラマは参照できない。

public string Name { get; }
public int Age { get; }

同じ型、同じ名前のプロパティを同じ順序で並べた匿名型は同じであることが保証されている。即ち、以下のコード:

var her = new { Name = "Jane Doe", Age = 20 }
var him = new { Name = "John Doe", Age = 20 }

において、her.GetType() == him.GetType()true である。

配列宣言の型省略

new キーワードを用いた配列の宣言の際、型を省略できるようになった。匿名型の配列を宣言する際に威力を発揮する。

var a = new[] {"foo", "bar", null};
// 上の文は次のように解釈される:
string[] a = new string[] {"foo", "bar", null};
// 以下の文:
var a = new[] {"foo", "bar", 123};
// は次のように解釈されることなく、誤りとなる:
object[] a = new object[] {"foo", "bar", 123};

クエリ式

LINQ をサポートするために、クエリ式が導入された。これは SQL の構文に類似しており、最終的に通常のメソッド呼び出しに変換されるものである。以下に例を示す:

var passedStudents =
  from s in students
  where s.MathScore + s.MusicScore + s.EnglishScore > 200
  select s.Name;

上のコードは以下のように変換される:

var passedStudents = students
  .Where(s => s.MathScore + s.MusicScore + s.EnglishScore > 200)
  .Select(s => s.Name);

C# 3.0で追加された構文の多くは式であるため、より巨大な式(当然クエリ式も含まれる)の一部として組み込むことができる。旧来複数の文に分けたり、作業用の変数を用意して記述していたコードを単独の式としてより簡潔に記述できる可能性がある。

出井秀行著の『実戦で役立つ C#プログラミングのイディオム/定石&パターン』(技術評論社、2017年)という書籍ではクエリ構文よりメソッド構文を推奨しており、クエリ構文ではLINQの全ての機能を使用できるわけではないこと、メソッド呼び出しは処理を連続して読める可読性があること、メソッド呼び出しであればMicrosoft Visual Studioの強力なインテリセンスが利用できることを理由に、著者はクエリ構文をほとんど使用していないと記している。

C# 4.0からの仕様

dynamicキーワード

dynamicキーワードが導入され、動的型付け変数を定義できるようになった。dynamic型として宣言されたオブジェクトに対する操作のバインドは実行時まで遅延される。

// xはint型と推論される:
var x = 1; 
// yはdynamic型として扱われる:
dynamic y = 2; 

public dynamic GetValue(dynamic obj)
{
  // objにValueが定義されていなくとも、コンパイルエラーとはならない:
  return obj.Value;
}

オプション引数・名前付き引数

VBC++に実装されているオプション引数・名前付き引数が、C#でも利用できるようになった。

public void MethodA()
{
  // 第1引数と第2引数を指定、第3引数は未指定:
  Console.WriteLine("Ans: " + MethodB(1, 2));  // Ans: 3 … 1 + 2 + 0となっている

  // 第1引数と第3引数を指定、第2引数は未指定:
  Console.WriteLine("Ans: " + MethodB(A: 1, C: 3));  // Ans: 4 … 1 + 0 + 3となっている
}

// 引数が指定されなかった場合のデフォルト値を等号で結ぶ:
public int MethodB(int A = 0, int B = 0, int C = 0)
{
  return A + B + C;
}

ジェネリクスの共変性・反変性

ジェネリクスの型引数に対してin、out修飾子を指定することにより、ジェネリクスの共変性・反変性を指定できるようになった。

IEnumerable<string> x = new List<string> { "a", "b", "c" };
// IEnumerable<T>インターフェイスは型引数にout修飾子が指定されているため、共変である。
// したがって、C# 4.0では次の行はコンパイルエラーにならない
IEnumerable<object> y = x;

C# 5.0からの仕様

  • 非同期処理 (await, async)
  • Caller Info 属性
  • foreach の仕様変更

C# 6.0からの仕様

  • 自動実装プロパティの初期化子
  • get のみの自動実装プロパティおよびコンストラクタ代入
  • パラメータなしの struct コンストラクタ
  • 静的 using ステートメント
  • Dictionary 初期化子
  • catch/finally での await
  • 例外フィルタ
  • Expression-bodied メンバ
  • null条件演算子
  • 文字列補間(テンプレート文字列)
  • nameof 演算子
  • #pragma
  • コレクションの初期化子での拡張メソッド
  • オーバーロード解決の改善

静的 using ステートメント

静的 using ステートメントを利用することで、型名の指定無しに他クラスの静的メンバの呼び出しを行えるようになった。
利用するにはusing staticの後に完全修飾なクラス名を指定する。

using static System.Math;
// ↑ソースコードの上部で宣言
class Hogehoge {
    // System.Math.Pow() , System.Math.PI を修飾無しで呼び出す
    double area = Pow(radius, 2) * PI;
}

例外フィルタ

catchの後にwhenキーワードを使用することで、処理する例外を限定することができるようになった。

try {
    // ...
}
catch (AggregateException ex) when (ex.InnerException is ArgumentException) {
    // ...
}

C# 7.0からの仕様

  • 出力変数宣言
  • パターンマッチング (is 式/switch 文)
  • タプル (タプル記法/分解/値の破棄)
  • ローカル関数
  • 数値リテラルの改善(桁セパレータ/バイナリリテラル)
  • ref戻り値、ref変数
  • 非同期戻り値型の汎用化
  • Expression-bodied 機能の拡充(コンストラクタ/デストラクタ/get/set/add/remove)
  • Throw 式

出力変数宣言

out引数で値を受け取る場合、その場所で変数宣言可能となった。

total += int.TryParse("123", out var num) ? num : 0;

パターンマッチング

is 式の拡張

is式の構文が拡張され、型の後ろに変数名を宣言できるようになった。 拡張されたis式はマッチした場合に宣言した変数にキャストした値を代入し、さらにtrueと評価される。 マッチしなかった場合はfalseと評価され、宣言した変数は未初期化状態となる。

void CheckAndSquare(object obj) {
    // objの型チェックと同時にnumに値を代入する。
    if (obj is int num && num >= 0) {
        num = num * num;
    }
    else {
        num = 0;
    }
    // if文の条件セクションは、ifの外側と同じスコープ
    Console.WriteLine(num);
}
switch 文の拡張

switch文のマッチ方法が拡張され、caseラベルに従来の「定数パターン」に加え、新たに「型パターン」を指定できるようになった。 また、「型パターン」のcaseラベルでは、when句に条件を指定することができる。 「型パターン」を含むswitch文では、必ずしも条件が排他的でなくなったため、最初にマッチしたcaseラベルの処理が実行される。 [5]

void Decide(object obj) {
    switch (obj) {
        case int num when num < 0:
            Console.WriteLine($"{num}は負の数です。");
            break;
        case int num:
            Console.WriteLine($"{num}を二乗すると{num * num}です。");
            break;
        case "B":
            Console.WriteLine($"これはBです。");
            break;
        case string str when str.StartsWith("H"):
            Console.WriteLine($"{str}はHから始まる文字列です。");
            break;
        case string str:
            Console.WriteLine($"{str}は文字列です。");
            break;
        case null:
            Console.WriteLine($"nullです");
            break;
        default:
            Console.WriteLine("判別できませんでした");
            break;
    }
}

ref戻り値、ref変数

refキーワードの使用方法が拡張された。
これによって、安全な参照の使い道が広がった。

ref戻り値

戻り値の型をrefで修飾することで、オブジェクトの参照を戻り値とすることができる。

// 二つの参照引数の内、値の大きいものの参照戻り値を返す
static ref int Max(ref int left,ref int right) {
    if(left >= right) {
        return ref left;
    }
    else {
        return ref right;
    }
}

変数の寿命は変わらないため、メソッド終了時に破棄されるローカル変数をref戻り値とすることはできない。

static int s_count = 1;

// メンバーの参照はref戻り値になる。
static ref int ReturnMember() {
    return ref s_count;
}
// ref引数はもちろんref戻り値になる。
static ref int ReturnRefParam(ref int something) {
    return ref something;
}
// ローカル変数をref戻り値とすることはできない。
// static ref int ReturnLocal() {
//     int x = 1;
//     return ref x;
// }
ref変数

ローカル変数の型をrefで修飾することで、参照を代入することができる。

// 参照戻り値を参照変数で受け取る
ref int max = ref Max(ref x, ref y);
// limitとmaxは同じ値を参照する
ref int limit = ref max;

C# 7.1からの仕様

非同期なMainメソッド

Mainメソッドの戻り値として、Task型、Task(int)型が認められた。

static Task Main()
static Task<int> Main()

default式

型推論可能な場面では、defaultの型指定は省略可能となった。

int number = default;
string name = default;

実装

C#の言語仕様は標準化団体Ecma Internationalを通じて公開・標準化されており、第三者がマイクロソフトとは無関係にコンパイラや実行環境を実装することができる。 現段階で、C#コンパイラの実装は次の5つが知られている。

  • マイクロソフト製
    • Visual Studio 2015 以降で使用されている、.NET コンパイラ プラットフォーム(開発名Roslyn)。ApacheライセンスオープンソースプロジェクトでGitHubで公開されている[6]WindowsmacOSLinuxで動作する。C#のコンパイラはC#、VB.NETのコンパイラはVB.NETで実装されている。以前のコンパイラと比べて、リファクタリングやIDE、スクリプティングなどへの利用が可能なAPIが公開されており、コンパイラ以外への様々な応用が可能。
    • Visual Studio 2013 まで使われていた、マイクロソフトによるVisual C# コンパイラ。
    • 2006年のC# 2.0当時の、マイクロソフトによるShared Source Common Language Infrastructure。共通言語基盤 (CLI) とC#コンパイラがソースコードで公開されている。
  • Mono ProjectによるMono内の Mono Compiler Suite (mcs)。
  • 2012年まで開発されていた、DotGNU ProjectによるPortable.NET内の the C-Sharp code compiler (cscc)。

名称

  • ECMA-334 4th edition によると、C# は「C Sharp」(シーシャープ)と発音し、「C#」 (LATIN CAPITAL LETTER C (U+0043) の後にNUMBER SIGN # (U+0023)) と書く [7]。 音楽のシャープ (♯, MUSIC SHARP SIGN (U+266F)) ではなくナンバーサイン (#) を採用したのは、フォントやブラウザなどの技術的な制約に加え、標準的キーボードには前者の記号が存在しないためである。
  • "#"接尾辞は、既存言語から派生した多くの.NET言語にも使用されている。これには、J#(Javaのマイクロソフトによる実装)、A#(Adaから)、F#(おそらくMLファミリに使われた型システムのSystem Fから[要出典])が含まれる。この接尾辞はGtk#GTK+などのGNOMEライブラリの.NETラッパ)、Cocoa#(Cocoaのラッパ)などのライブラリにも使用されている。
  • C#という名称の解釈として、「(A~Gで表された)直前の音を半音上げる」という音楽記号の役割に着目し、「C言語を改良したもの」を意味したのではないか、というものがある。これは、C++の名称が「C言語を1つ進めたもの」という意味でつけられたことにも似ている。
  • アンダース・ヘルスバーグは、「C#」が「C++++」(すなわち「C++をさらに進めたもの」)にみえるのが由来である、と語っている。[8][9]

脚注

  1. ^ Standard ECMA-334 C# Language Specification
  2. ^ ISO/IEC 23270:2003 C# Language Specification
  3. ^ JIS X 3015 プログラミング言語C#
  4. ^ null 許容型のボックス化 (C# プログラミング ガイド) MSDNライブラリ
  5. ^ https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/switch
  6. ^ dotnet/roslyn - GitHub
  7. ^ Standard ECMA-334 C# Language Specification
  8. ^ レポート:コミュニティスペシャルセッション with Anders Hejlsberg in Microsoft Developers Conference 2006
  9. ^ C#への期待。アンダースからの返答

関連項目

外部リンク


C♯

(C Sharp から転送)

出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2009/09/15 10:12 UTC 版)

C♯(シーシャープ)






固有名詞の分類


英和和英テキスト翻訳>> Weblio翻訳
英語⇒日本語日本語⇒英語
  

辞書ショートカット

カテゴリ一覧

全て

ビジネス

業界用語

コンピュータ

電車

自動車・バイク

工学

建築・不動産

学問

文化

生活

ヘルスケア

趣味

スポーツ

生物

食品

人名

方言

辞書・百科事典

すべての辞書の索引

「C Sharp」の関連用語

C Sharpのお隣キーワード

   

英語⇒日本語
日本語⇒英語
   
検索ランキング

画像から探す

松尾歩

アフリカスイギュウ

田中義一

上村 邦夫

ペーパードリップ

移動無線電話車

小見川

バナナハート





C Sharpのページの著作権
Weblio 辞書情報提供元は参加元一覧にて確認できます。

  
ウィキペディアウィキペディア
All text is available under the terms of the GNU Free Documentation License.
この記事は、ウィキペディアのC Sharp (改訂履歴)、C♯ (改訂履歴)の記事を複製、再配布したものにあたり、GNU Free Documentation Licenseというライセンスの下で提供されています。 Weblio辞書に掲載されているウィキペディアの記事も、全てGNU Free Documentation Licenseの元に提供されております。

©2017 Weblio RSS