Csharp-quick-guide

提供:Dev Guides
移動先:案内検索

C#-概要

C#は、マイクロソフトが開発し、欧州コンピューター製造業者協会(ECMA)および国際標準化機構(ISO)によって承認された、最新の汎用オブジェクト指向プログラミング言語です。

C#は、.Net Frameworkの開発中にAnders Hejlsbergと彼のチームによって開発されました。

C#はCommon Language Infrastructure(CLI)用に設計されています。CLIは、実行可能なコードとランタイム環境で構成され、さまざまなコンピュータープラットフォームとアーキテクチャでさまざまな高レベル言語を使用できます。

次の理由により、C#は広く使用されている専門的な言語になります-

  • 最新の汎用プログラミング言語です
  • オブジェクト指向です。
  • コンポーネント指向です。
  • 学ぶのは簡単です。
  • これは構造化言語です。
  • 効率的なプログラムを生成します。
  • さまざまなコンピュータープラットフォームでコンパイルできます。
  • これは.Net Frameworkの一部です。

C#の強力なプログラミング機能

C#の構成体は、従来の高レベル言語、CおよびC ++に密接に従っていますが、オブジェクト指向プログラミング言語です。 Javaと非常によく似ており、世界中の多くのプログラマーに愛されている数多くの強力なプログラミング機能を備えています。

以下は、C#のいくつかの重要な機能のリストです-

  • ブール条件
  • 自動ガベージコレクション
  • 標準ライブラリ
  • アセンブリのバージョン管理
  • プロパティとイベント
  • デリゲートとイベント管理
  • 使いやすいジェネリック
  • インデクサー
  • 条件付きコンパイル
  • シンプルなマルチスレッド
  • LINQとラムダ式
  • Windowsとの統合

C#-環境

この章では、C#プログラミングの作成に必要なツールについて説明します。 C#は.Netフレームワークの一部であり、.Netアプリケーションの作成に使用されることは既に述べました。 したがって、C#プログラムを実行するために利用可能なツールについて説明する前に、C#が.Netフレームワークとどのように関係するかを理解しましょう。

.Net Framework

  • Windowsアプリケーション
  • Webアプリケーション
  • ウェブサービス
  • 共通言語ランタイム(CLR)
  • .Net Frameworkクラスライブラリ
  • 共通言語仕様
  • 共通型システム
  • メタデータとアセンブリ
  • Windowsフォーム
  • ASP.NetおよびASP.Net AJAX
  • ADO.Net
  • Windowsワークフロー財団(WF)
  • Windows Presentation Foundation
  • Windowsコミュニケーション財団(WCF)
  • LINQ

これらの各コンポーネントが実行するジョブについては、リンク:/asp.net/asp.net_introduction [ASP.Net-はじめに]を参照してください。各コンポーネントの詳細については、Microsoftのドキュメントを参照してください。

C#の統合開発環境(IDE)

Microsoftは、C#プログラミング用に次の開発ツールを提供しています-

  • Visual Studio 2010(VS)
  • Visual C#2010 Express(VCE) *ビジュアルWeb開発者

最後の2つは、Microsoftの公式Webサイトから無料で入手できます。 これらのツールを使用すると、単純なコマンドラインアプリケーションからより複雑なアプリケーションまで、あらゆる種類のC#プログラムを作成できます。 メモ帳などの基本的なテキストエディターを使用してC#ソースコードファイルを記述し、.NET Frameworkの一部であるコマンドラインコンパイラーを使用してコードをアセンブリにコンパイルすることもできます。

Visual C#ExpressおよびVisual Web Developer Expressエディションは、Visual Studioの短縮バージョンであり、外観は同じです。 Visual Studioのほとんどの機能を保持します。 このチュートリアルでは、Visual C#2010 Expressを使用しました。

Microsoft Visual Studioからダウンロードできます。 マシンに自動的にインストールされます。

注:Express Editionをインストールするには、アクティブなインターネット接続が必要です。

LinuxまたはMac OSでのC#プログラムの作成

NET FrameworkはWindowsオペレーティングシステムで実行されますが、他のオペレーティングシステムで動作する代替バージョンがいくつかあります。* Mono *は、C#コンパイラを含む.NET Frameworkのオープンソースバージョンであり、LinuxやMac OSのさまざまなフレーバーを含むいくつかのオペレーティングシステムで実行されます。 Go Monoを確認してください。.

Monoの目的は、Microsoft .NETアプリケーションをクロスプラットフォームで実行できるようにするだけでなく、Linux開発者により良い開発ツールを提供することでもあります。 Monoは、Android、BSD、iOS、Linux、OS X、Windows、Solaris、UNIXなどの多くのオペレーティングシステムで実行できます。

C#-プログラム構造

C#プログラミング言語の基本的な構成要素を検討する前に、今後の章で参照として使用できるように、最低限のC#プログラム構造を見てみましょう。

Hello Worldプログラムの作成

C#プログラムは、次の部分で構成されています-

  • 名前空間宣言
  • クラス
  • クラスメソッド
  • クラス属性
  • 主な方法
  • ステートメントと式
  • コメント

「Hello World」という言葉を印刷する簡単なコードを見てみましょう-

using System;

namespace HelloWorldApplication {
   class HelloWorld {
      static void Main(string[] args) {
        /*my first program in C#*/
         Console.WriteLine("Hello World");
         Console.ReadKey();
      }
   }
}

このコードをコンパイルして実行すると、次の結果が生成されます-

Hello World

私たちは与えられたプログラムのさまざまな部分を見てみましょう-

  • プログラムの最初の行 using System; - using キーワードは、プログラムに System 名前空間を含めるために使用されます。 通常、プログラムには複数の using ステートメントがあります。
  • 次の行には namespace 宣言があります。 *名前空間*はクラスのコレクションです。 _HelloWorldApplication_名前空間には、_HelloWorld_クラスが含まれています。
  • 次の行には class 宣言があります。クラス_HelloWorld_には、プログラムが使用するデータとメソッドの定義が含まれています。 通常、クラスには複数のメソッドが含まれます。 メソッドは、クラスの動作を定義します。 ただし、_HelloWorld_クラスには Main メソッドが1つしかありません。
  • 次の行は、すべてのC#プログラムの*エントリポイント*である Main メソッドを定義します。 Main メソッドは、実行時にクラスが実行することを示します。
  • 次の行/…​/はコンパイラによって無視され、プログラムに*コメント*を追加するために挿入されます。
  • Mainメソッドは、ステートメント Console.WriteLine( "Hello World"); でその動作を指定します + _WriteLine_は、_System_名前空間で定義された_Console_クラスのメソッドです。 このステートメントにより、「Hello、World!」というメッセージが表示されます。画面に表示されます。
  • 最後の行 Console.ReadKey(); はVS.NETユーザー向けです。 これにより、プログラムはキーが押されるまで待機し、プログラムがVisual Studio .NETから起動されたときに画面がすばやく実行されて閉じられなくなります。

次の点に注意する価値があります-

  • C#は大文字と小文字を区別します。
  • すべてのステートメントと式はセミコロン(;)で終わる必要があります。
  • プログラムの実行は、Mainメソッドで開始されます。
  • Javaとは異なり、プログラムファイル名はクラス名と異なる場合があります。

プログラムのコンパイルと実行

C#プログラムのコンパイルと実行にVisual Studio.Netを使用している場合は、次の手順を実行します-

  • Visual Studioを起動します。
  • メニューバーで、[ファイル]→ [新規]→ [プロジェクト]を選択します。
  • テンプレートからVisual C#を選択し、Windowsを選択します。
  • コンソールアプリケーションを選択します。
  • プロジェクトの名前を指定し、[OK]ボタンをクリックします。
  • これにより、ソリューションエクスプローラーに新しいプロジェクトが作成されます。
  • コードエディターでコードを記述します。
  • [実行]ボタンをクリックするか、F5キーを押してプロジェクトを実行します。 行Hello Worldを含むコマンドプロンプトウィンドウが表示されます。

Visual Studio IDEの代わりにコマンドラインを使用してC#プログラムをコンパイルできます-

  • テキストエディターを開き、上記のコードを追加します。
  • ファイルを helloworld.cs として保存します
  • コマンドプロンプトツールを開き、ファイルを保存したディレクトリに移動します。
  • csc helloworld.cs と入力し、Enterキーを押してコードをコンパイルします。
  • コードにエラーがない場合、コマンドプロンプトは次の行に移動し、 helloworld.exe 実行可能ファイルを生成します。
  • helloworld と入力して、プログラムを実行します。
  • 画面に出力されるHello Worldを確認できます。

C#-基本構文

C#はオブジェクト指向プログラミング言語です。 オブジェクト指向プログラミングの方法論では、プログラムはアクションによって相互作用するさまざまなオブジェクトで構成されます。 オブジェクトが実行できるアクションはメソッドと呼ばれます。 同じ種類のオブジェクトは、同じタイプを持つか、同じクラスにあると言われます。

たとえば、Rectangleオブジェクトを考えてみましょう。 長さや幅などの属性があります。 設計によっては、これらの属性の値を受け入れ、面積を計算し、詳細を表示する方法が必要になる場合があります。

Rectangleクラスの実装を見て、C#の基本的な構文について議論しましょう-

using System;

namespace RectangleApplication {
   class Rectangle {

     //member variables
      double length;
      double width;

      public void Acceptdetails() {
         length = 4.5;
         width = 3.5;
      }
      public double GetArea() {
         return length * width;
      }
      public void Display() {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }
   class ExecuteRectangle {
      static void Main(string[] args) {
         Rectangle r = new Rectangle();
         r.Acceptdetails();
         r.Display();
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Length: 4.5
Width: 3.5
Area: 15.75

_using_キーワード

C#プログラムの最初のステートメントは

using System;
*using* キーワードは、プログラムに名前空間を含めるために使用されます。 プログラムには、複数のusingステートメントを含めることができます。

_class_キーワード

*class* キーワードは、クラスの宣言に使用されます。

C#のコメント

コメントはコードの説明に使用されます。 コンパイラはコメントエントリを無視します。 C#プログラムの複数行コメントは/で始まり、以下に示すように文字/で終了します-

/*This program demonstrates
The basic syntax of C# programming
Language*/

単一行コメントは、「//」記号で示されます。 例えば、

}//end class Rectangle

メンバー変数

変数は、データを保存するために使用されるクラスの属性またはデータメンバーです。 上記のプログラムでは、_Rectangle_クラスに_length_および_width_という名前の2つのメンバー変数があります。

メンバー関数

関数は、特定のタスクを実行する一連のステートメントです。 クラスのメンバー関数は、クラス内で宣言されます。 サンプルクラスRectangleには、AcceptDetails _、 GetArea Display_の3つのメンバー関数が含まれています。

クラスのインスタンス化

上記のプログラムでは、_ExecuteRectangle_クラスに_Main()_メソッドが含まれており、_Rectangle_クラスをインスタンス化します。

識別子

識別子は、クラス、変数、関数、またはその他のユーザー定義アイテムを識別するために使用される名前です。 C#でクラスに名前を付けるための基本的なルールは次のとおりです-

  • 名前は文字で始まり、その後に一連の文字、数字(0〜9)、またはアンダースコアが続く必要があります。 識別子の最初の文字を数字にすることはできません。
  • 次のような埋め込みスペースや記号を含めることはできませんか? - + ! @#%^&*()[] \ {} ; : "'/および\。 ただし、アンダースコア(_)は使用できます。
  • C#キーワードであってはなりません。

C#キーワード

キーワードは、C#コンパイラに事前定義された予約語です。 これらのキーワードは識別子として使用できません。 ただし、これらのキーワードを識別子として使用する場合は、キーワードの前に@文字を付けることができます。

C#では、getやsetなどの一部の識別子はコードのコンテキストで特別な意味を持ち、コンテキストキーワードと呼ばれます。

次の表に、C#で予約されているキーワードとコンテキストキーワードを示します-

予約済みキーワード

抽象

as

base

bool

ブレーク

byte

case

キャッチ

char

チェック済み

クラス

const

持続する

小数

デフォルト

代表者

do

ダブル

else

enum

イベント

明白な

外面

最後に

一定

浮く

for

前々

goto

if

暗黙

in

in(汎用修飾子)

int

インタフェース

内部

is

lock

long

名前空間

new

null

オペレーター

out

out(汎用修飾子)

オーバーライド

パラーム

非公開

保護された

パブリック

読み取り専用

ref

戻る

スバイト

封印

ショート

のサイズ

stackalloc

静的

ひも

構造体

スイッチ

this

スロー

true

try

typeof

uint

ulong

未チェック

危険です

Ushort

使う

バーチャル

void

揮発性

しながら

コンテキストキーワード

add

エイリアス

上昇

降順

動的

from

get

グローバル

グループ

into

join

let

注文する

部分(タイプ)

部分的(メソッド)

削除する

選択する

set

C#-データ型

C#の変数は、次のタイプに分類されます-

  • 値タイプ
  • 参照タイプ
  • ポインターの種類

値のタイプ

値型変数には、値を直接割り当てることができます。 これらは System.ValueType クラスから派生しています。

値タイプにはデータが直接含まれます。 例としては、 int、char、およびfloat があり、それぞれ数値、アルファベット、および浮動小数点数が格納されます。 int 型を宣言すると、システムは値を保存するためにメモリを割り当てます。

次の表に、C#2010で使用可能な値の種類を示します-

Type Represents Range Default Value
bool Boolean value True or False False
byte 8-bit unsigned integer 0 to 255 0
char 16-bit Unicode character U +0000 to U +ffff '\0'
decimal 128-bit precise decimal values with 28-29 significant digits (-7.9 x 1028 to 7.9 x 1028)/100 to 28 0.0M
double 64-bit double-precision floating point type (/-)5.0 x 10^-324^ to (/-)1.7 x 10308 0.0D
float 32-bit single-precision floating point type -3.4 x 1038 to + 3.4 x 1038 0.0F
int 32-bit signed integer type -2,147,483,648 to 2,147,483,647 0
long 64-bit signed integer type -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 0L
sbyte 8-bit signed integer type -128 to 127 0
short 16-bit signed integer type -32,768 to 32,767 0
uint 32-bit unsigned integer type 0 to 4,294,967,295 0
ulong 64-bit unsigned integer type 0 to 18,446,744,073,709,551,615 0
ushort 16-bit unsigned integer type 0 to 65,535 0

特定のプラットフォームで型または変数の正確なサイズを取得するには、 sizeof メソッドを使用できます。 式_sizeof(type)_は、オブジェクトまたはタイプのストレージサイズをバイト単位で生成します。 以下は、任意のマシンで_int_型のサイズを取得する例です-

using System;

namespace DataTypeApplication {
   class Program {
      static void Main(string[] args) {
         Console.WriteLine("Size of int: {0}", sizeof(int));
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Size of int: 4

参照タイプ

参照タイプには、変数に格納された実際のデータは含まれませんが、変数への参照が含まれます。

つまり、メモリの場所を指します。 複数の変数を使用すると、参照型はメモリの場所を参照できます。 メモリー位置のデータが変数の1つによって変更されると、他の変数はこの値の変更を自動的に反映します。 組み込み*参照タイプの例は、 *object 、* dynamic、、および *string です。

オブジェクトタイプ

  • オブジェクト型*は、C#Common Type System(CTS)のすべてのデータ型の究極の基本クラスです。 オブジェクトはSystem.Objectクラスのエイリアスです。 オブジェクトタイプには、他のタイプ、値タイプ、参照タイプ、定義済みまたはユーザー定義のタイプの値を割り当てることができます。 ただし、値を割り当てる前に、型変換が必要です。

値型がオブジェクト型に変換されるとき、それは boxing と呼ばれ、オブジェクト型が値型に変換されるとき、それは unboxing と呼ばれます。

object obj;
obj = 100;//this is boxing

ダイナミックタイプ

動的データ型変数には、任意のタイプの値を格納できます。 これらのタイプの変数のタイプチェックは、実行時に行われます。

動的型を宣言するための構文は-

dynamic <variable_name> = value;

例えば、

dynamic d = 20;

動的型はオブジェクト型に似ていますが、オブジェクト型変数の型チェックはコンパイル時に行われるのに対して、動的型変数の型チェックは実行時に行われます。

文字列タイプ

*String Type* を使用すると、文字列値を変数に割り当てることができます。 文字列型は、System.Stringクラスのエイリアスです。 オブジェクトタイプから派生します。 文字列型の値は、引用符付きと@quotedの2つの形式の文字列リテラルを使用して割り当てることができます。

例えば、

String str = "Tutorials Point";

@quoted文字列リテラルは次のようになります-

@"Tutorials Point";

ユーザー定義の参照タイプは、クラス、インターフェース、またはデリゲートです。 これらのタイプについては、後の章で説明します。

ポインターの種類

ポインタ型変数には、別の型のメモリアドレスが格納されます。 C#のポインターには、CまたはC ++のポインターと同じ機能があります。

ポインタ型を宣言するための構文は-

type* identifier;

例えば、

char* cptr;
int* iptr;

ポインターの種類については、「安全でないコード」の章で説明します。

C#-型変換

型変換とは、あるタイプのデータを別のタイプに変換することです。 型キャストとも呼ばれます。 C#では、型キャストには2つの形式があります-

  • 暗黙的な型変換-これらの変換は、C#によって型保証された方法で実行されます。 たとえば、小さい整数型から大きい整数型への変換、派生クラスから基本クラスへの変換などです。
  • 明示的な型変換-これらの変換は、事前定義された関数を使用してユーザーが明示的に行います。 明示的な変換にはキャスト演算子が必要です。

次の例は、明示的な型変換を示しています-

using System;

namespace TypeConversionApplication {
   class ExplicitConversion {
      static void Main(string[] args) {
         double d = 5673.74;
         int i;

        //cast double to int.
         i = (int)d;
         Console.WriteLine(i);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

5673

C#型の変換方法

C#は、次の組み込み型変換メソッドを提供します-

Sr.No. Methods & Description
1

ToBoolean

可能な場合、タイプをブール値に変換します。

2

ToByte

型をバイトに変換します。

3

ToChar

可能な場合、タイプを単一のUnicode文字に変換します。

4

ToDateTime

型(整数型または文字列型)を日時構造体に変換します。

5

ToDecimal

浮動小数点または整数型を10進数型に変換します。

6

ToDouble

型をdouble型に変換します。

7

ToInt16

型を16ビット整数に変換します。

8

ToInt32

型を32ビット整数に変換します。

9

ToInt64

型を64ビット整数に変換します。

10

ToSbyte

型を符号付きバイト型に変換します。

11

ToSingle

型を小さな浮動小数点数に変換します。

12

ToString

型を文字列に変換します。

13

ToType

タイプを指定されたタイプに変換します。

14

ToUInt16

型をunsigned int型に変換します。

15

ToUInt32

型を符号なしlong型に変換します。

16

ToUInt64

型を符号なしの大きな整数に変換します。

次の例では、さまざまな値の型を文字列型に変換します-

using System;

namespace TypeConversionApplication {
   class StringConversion {
      static void Main(string[] args) {
         int i = 75;
         float f = 53.005f;
         double d = 2345.7652;
         bool b = true;

         Console.WriteLine(i.ToString());
         Console.WriteLine(f.ToString());
         Console.WriteLine(d.ToString());
         Console.WriteLine(b.ToString());
         Console.ReadKey();

      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

75
53.005
2345.7652
True

C#-変数

変数は、プログラムが操作できるストレージ領域に付けられた名前に他なりません。 C#の各変数には特定の型があり、変数のメモリのサイズとレイアウト、そのメモリ内に格納できる値の範囲、および変数に適用できる操作のセットを決定します。

C#で提供される基本的な値の種類は次のように分類できます-

Type Example
Integral types sbyte, byte, short, ushort, int, uint, long, ulong, and char
Floating point types float and double
Decimal types decimal
Boolean types true or false values, as assigned
Nullable types Nullable data types

C#では、 enum などの変数の他の値型と、 class などの変数の参照型を定義することもできます。これについては、以降の章で説明します。

変数の定義

C#での変数定義の構文は-

<data_type> <variable_list>;

ここで、data_typeはchar、int、float、double、またはユーザー定義のデータ型を含む有効なC#データ型である必要があり、variable_listはコンマで区切られた1つ以上の識別子名で構成されます。

いくつかの有効な変数定義はここに示されています-

int i, j, k;
char c, ch;
float f, salary;
double d;

あなたは次のように定義時に変数を初期化することができます-

int i = 100;

変数の初期化

変数は、等号とそれに続く定数式で初期化されます(値が割り当てられます)。 初期化の一般的な形式は-

variable_name = value;

変数は宣言で初期化できます。 初期化子は、等号とそれに続く定数式で構成されます-

<data_type> <variable_name> = value;

いくつかの例は-

int d = 3, f = 5;   /*initializing d and f.*/
byte z = 22;        /*initializes z.*/
double pi = 3.14159;/*declares an approximation of pi.*/
char x = 'x';       /*the variable x has the value 'x'.*/

変数を適切に初期化するのは良いプログラミング手法です。そうしないと、プログラムで予期しない結果が生じる場合があります。

次の例では、さまざまなタイプの変数を使用します-

using System;

namespace VariableDefinition {
   class Program {
      static void Main(string[] args) {
         short a;
         int b ;
         double c;

        /*actual initialization*/
         a = 10;
         b = 20;
         c = a + b;
         Console.WriteLine("a = {0}, b = {1}, c = {2}", a, b, c);
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

a = 10, b = 20, c = 30

ユーザーからの値の受け入れ

*System* 名前空間の *Console* クラスは、ユーザーからの入力を受け入れて変数に保存するための関数* ReadLine()*を提供します。

例えば、

int num;
num = Convert.ToInt32(Console.ReadLine());
  • Console.ReadLine()は文字列形式のデータを受け入れるため、関数 Convert.ToInt32()*はユーザーが入力したデータをintデータ型に変換します。

C#の左辺値と右辺値式

C#には2種類の式があります-

  • 左辺値-左辺値である式は、割り当ての左辺または右辺のいずれかとして表示される場合があります。
  • rvalue -右辺値である式は、割り当ての右側ではなく左側に表示されます。

変数は左辺値であるため、割り当ての左側に表示される場合があります。 数値リテラルは右辺値であるため、割り当てられない可能性があり、左側に表示できません。 以下は有効なC#ステートメントです-

int g = 20;

しかし、以下は有効なステートメントではなく、コンパイル時エラーを生成します-

10 = 20;

C#-定数とリテラル

定数は、プログラムの実行中に変更されない可能性がある固定値を参照します。 これらの固定値はリテラルとも呼ばれます。 定数には、整数定数、浮動定数、文字定数、文字列リテラルなどの基本的なデータ型を使用できます。 列挙定数もあります。

定数は、定義後に値を変更できないことを除いて、通常の変数と同様に扱われます。

整数リテラル

整数リテラルは、10進数または16進数の定数です。 プレフィックスは、基数または基数を指定します。16進数の場合は0xまたは0Xであり、10進数の場合はプレフィックスIDはありません。

整数リテラルには、UとLを組み合わせたサフィックスを付けることもできます。それぞれ、符号なしとロングを表します。 接尾辞は大文字でも小文字でも、任意の順序で指定できます。

ここに整数リテラルのいくつかの例があります-

212        /*Legal*/
215u       /*Legal*/
0xFeeL     /*Legal*/

以下は、整数リテラルのさまざまなタイプの他の例です-

85        /*decimal*/
0x4b      /*hexadecimal*/
30        /*int*/
30u       /*unsigned int*/
30l       /*long*/
30ul      /*unsigned long*/

浮動小数点リテラル

浮動小数点リテラルには、整数部、小数点、小数部、指数部があります。 浮動小数点リテラルは、10進数形式または指数形式で表現できます。

浮動小数点リテラルの例をいくつか示します-

3.14159      /*Legal*/
314159E-5F   /*Legal*/
510E         /*Illegal: incomplete exponent*/
210f         /*Illegal: no decimal or exponent*/
.e55         /*Illegal: missing integer or fraction*/

10進形式で表す場合、小数点、指数、またはその両方を含める必要があります。指数形式を使用して表現する場合、整数部、小数部、またはその両方を含める必要があります。 符号付き指数は、eまたはEによって導入されます。

文字定数

文字リテラルは単一引用符で囲まれます。 たとえば、「x」であり、char型の単純な変数に格納できます。 文字リテラルには、プレーン文字(「x」など)、エスケープシーケンス(「\ t」など)、またはユニバーサル文字(「\ u02C0」など)を使用できます。

バックスラッシュが前にある場合、C#には特定の文字があります。 これらは特別な意味を持ち、改行(\ n)またはタブ(\ t)のように表すために使用されます。 ここに、そのようなエスケープシーケンスコードのいくつかのリストがあります-

Escape sequence Meaning
\\ \ character
\' ' character
\" " character
\? ? character
\a Alert or bell
\b Backspace
\f Form feed
\n Newline
\r Carriage return
\t Horizontal tab
\v Vertical tab
\xhh . . . Hexadecimal number of one or more digits

以下は、いくつかのエスケープシーケンス文字を表示する例です-

using System;

namespace EscapeChar {
   class Program {
      static void Main(string[] args) {
         Console.WriteLine("Hello\tWorld\n\n");
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Hello   World

文字列リテラル

文字列リテラルまたは定数は、二重引用符 ""または@ ""で囲みます。 文字列には、文字リテラルに類似した文字が含まれます:プレーン文字、エスケープシーケンス、およびユニバーサル文字。

文字列リテラルを使用し、空白を使用して部分を分離すると、長い行を複数の行に分割できます。

文字列リテラルの例を次に示します。 3つの形式はすべて同じ文字列です。

"hello, dear"
"hello, \
dear"
"hello, " "d" "ear"
@"hello dear"

定数の定義

定数は、 const キーワードを使用して定義されます。 定数を定義するための構文は-

const <data_type> <constant_name> = value;

次のプログラムは、プログラムで定数を定義および使用する方法を示しています-

using System;

namespace DeclaringConstants {
   class Program {
      static void Main(string[] args) {
         const double pi = 3.14159;

        //constant declaration
         double r;
         Console.WriteLine("Enter Radius: ");
         r = Convert.ToDouble(Console.ReadLine());

         double areaCircle = pi *r* r;
         Console.WriteLine("Radius: {0}, Area: {1}", r, areaCircle);
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Enter Radius:
3
Radius: 3, Area: 28.27431

C#-演算子

演算子は、特定の数学的または論理的な操作を実行するようコンパイラーに指示する記号です。 C#には豊富な組み込み演算子があり、次のタイプの演算子を提供します-

  • 算術演算子
  • 関係演算子
  • 論理演算子
  • ビット演算子
  • 割り当て演算子
  • その他の演算子

このチュートリアルでは、算術演算子、関係演算子、論理演算子、ビット単位演算子、代入演算子、およびその他の演算子を1つずつ説明します。

算術演算子

次の表は、C#でサポートされているすべての算術演算子を示しています。 変数 A が10を保持し、変数 B が20を保持すると仮定します-

リンク:/csharp/csharp_arithmetic_operators [例を表示]

Operator Description Example
+ Adds two operands A + B = 30
- Subtracts second operand from the first A - B = -10
* Multiplies both operands A* B = 200
/ Divides numerator by de-numerator B/A = 2
% Modulus Operator and remainder of after an integer division B % A = 0
++ Increment operator increases integer value by one A++ = 11
 —  Decrement operator decreases integer value by one A-- = 9

関係演算子

次の表は、C#でサポートされているすべての関係演算子を示しています。 変数 A が10を保持し、変数 B が20を保持すると仮定します-

リンク:/csharp/csharp_relational_operators [例を表示]

Operator Description Example
== Checks if the values of two operands are equal or not, if yes then condition becomes true. (A == B) is not true.
!= Checks if the values of two operands are equal or not, if values are not equal then condition becomes true. (A != B) is true.
> Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true. (A > B) is not true.
< Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true. (A < B) is true.
>= Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true. (A >= B) is not true.
Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true. (A ⇐ B) is true.

論理演算子

次の表は、C#でサポートされているすべての論理演算子を示しています。 変数 A がブール値trueを保持し、変数 B がブール値falseを保持すると仮定します-

リンク:/csharp/csharp_logical_operators [例を表示]

Operator Description Example
&& Called Logical AND operator. If both the operands are non zero then condition becomes true. (A && B) is false.
Called Logical OR Operator. If any of the two operands is non zero then condition becomes true. (A
B) is true. ! Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true then Logical NOT operator will make false.

ビット演算子

ビットごとの演算子はビットに対して機能し、ビットごとの演算を実行します。 &、|、および^の真理値表は次のとおりです-

p q p & q p q
p ^ q 0 0 0 0
0 0 1 0 1
1 1 1 1 1
0 1 0 0 1

A = 60であると仮定します。およびB = 13;その後、バイナリ形式では、次のとおりです-

A = 0011 1100

B = 0000 1101

A&B = 0000 1100

A | B = 0011 1101

A ^ B = 0011 0001

〜A = 1100 0011

次の表に、C#でサポートされているビット演算子を示します。 変数Aが60を保持し、変数Bが13を保持すると仮定します-

リンク:/csharp/csharp_bitwise_operators [例を表示]

[cols=",,",options="header",]
|===
|Operator |Description |Example |& |Binary AND Operator copies a bit to the result if it exists in both operands. |(A & B) = 12, which is 0000 1100 || |Binary OR Operator copies a bit if it exists in either operand. |(A | B) = 61, which is 0011 1101 |^ |Binary XOR Operator copies the bit if it is set in one operand but not both. |(A ^ B) = 49, which is 0011 0001 |~ |Binary Ones Complement Operator is unary and has the effect of 'flipping' bits. |(~A ) = -61, which is 1100 0011 in 2's complement due to a signed binary number. |<< |Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. |A << 2 = 240, which is 1111 0000 |>> |Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. |A >> 2 = 15, which is 0000 1111
|===

=== 割り当て演算子

C#でサポートされている次の代入演算子があります-

リンク:/csharp/csharp_assignment_operators [例を表示]

[cols=",,",options="header",]
|===
|Operator |Description |Example |= |Simple assignment operator, Assigns values from right side operands to left side operand |C = A + B assigns value of A + B into C |+= |Add AND assignment operator, It adds right operand to the left operand and assign the result to left operand |C += A is equivalent to C = C + A |-= |Subtract AND assignment operator, It subtracts right operand from the left operand and assign the result to left operand |C -= A is equivalent to C = C - A |*= |Multiply AND assignment operator, It multiplies right operand with the left operand and assign the result to left operand |C *= A is equivalent to C = C * A |/= |Divide AND assignment operator, It divides left operand with the right operand and assign the result to left operand |C/= A is equivalent to C = C/A |%= |Modulus AND assignment operator, It takes modulus using two operands and assign the result to left operand |C %= A is equivalent to C = C % A |<<= |Left shift AND assignment operator |C <<= 2 is same as C = C << 2 |>>= |Right shift AND assignment operator |C >>= 2 is same as C = C >> 2 |&= |Bitwise AND assignment operator |C &= 2 is same as C = C & 2 |^= |bitwise exclusive OR and assignment operator |C ^= 2 is same as C = C ^ 2 ||= |bitwise inclusive OR and assignment operator |C |= 2 is same as C = C | 2
|===

=== その他の演算子

 *sizeof、typeof* 、*?など、他の重要な演算子はほとんどありません。 :* C#でサポートされています。

リンク:/csharp/csharp_misc_operators [例を表示]

[width="100%",cols="^34%,33%,33%",options="header",]
|===
|Operator |Description |Example |sizeof() |Returns the size of a data type. |sizeof(int), returns 4. |typeof() |Returns the type of a class. |typeof(StreamReader); |& |Returns the address of an variable. |&a; returns actual address of the variable. |* |Pointer to a variable. |*a; creates pointer named 'a' to a variable. |? : |Conditional Expression |If Condition is true ? Then value X : Otherwise value Y |is |Determines whether an object is of a certain type. |If( Ford is Car)//checks if Ford is an object of the Car class. |as |Cast without raising an exception if the cast fails. a| Object obj = new StringReader("Hello");

StringReader r = obj as StringReader;

|===

=== C#の演算子の優先順位

演算子の優先順位は、式内の用語のグループ化を決定します。 これは、式の評価に影響します。 特定の演算子は、他の演算子よりも優先順位が高くなっています。たとえば、乗算演算子は加算演算子よりも優先順位が高くなります。

たとえば、x = 7 + 3 * 2;ここでは、演算子*の優先順位が+より高いため、xには20ではなく13が割り当てられます。したがって、最初の評価は3 * 2で行われ、その後7が追加されます。

ここでは、優先順位が最も高い演算子が表の上部に表示され、優先順位が最も低い演算子が下部に表示されます。 式内では、優先順位の高い演算子が最初に評価されます。

リンク:/csharp/csharp_operators_precedence [例を表示]

[cols=",,",options="header",]
|===
|Category |Operator |Associativity |Postfix |() [] -> . ++ - - |Left to right |Unary |+ - ! ~ ++ - - (type)* & sizeof |Right to left |Multiplicative | */% |Left to right |Additive |+ - |Left to right |Shift |<< >> |Left to right |Relational |< <= > >= |Left to right |Equality |== != |Left to right |Bitwise AND |& |Left to right |Bitwise XOR |^ |Left to right |Bitwise OR || |Left to right |Logical AND |&& |Left to right |Logical OR ||| |Left to right |Conditional |?: |Right to left |Assignment |= += -=* =/= %=>>= <<= &= ^= |= |Right to left |Comma |, |Left to right
|===

C#-意思決定

意思決定構造では、プログラマーは、プログラムが評価またはテストする1つ以上の条件を、条件が真であると判断された場合に実行されるステートメント、およびオプションで条件が実行された場合に実行される他のステートメントとともに指定する必要があります偽と判断されます。

以下は、ほとんどのプログラミング言語で見られる典型的な意思決定構造の一般的な形式です-

C#での意思決定ステートメント

C#は、次のタイプの意思決定ステートメントを提供します。 詳細を確認するには、次のリンクをクリックしてください。

Sr.No. Statement & Description
1

if statement

  • ifステートメント*は、ブール式とそれに続く1つ以上のステートメントで構成されます。
2

if…​else statement

  • ifステートメント*の後にオプションの* elseステートメント*を続けることができます。これはブール式がfalseの場合に実行されます。
3

nested if statements

1つの if または else if ステートメントを別の if または else if ステートメント内で使用できます。

4

switch statement

  • switch* ステートメントを使用すると、変数を値のリストと等しいかどうかをテストできます。
5

nested switch statements

1つの switch ステートメントを別の switch ステートメント内で使用できます。

は? :オペレーター

条件演算子? :*前の章の *if …​ else ステートメントを置き換えるために使用できます。 それは次の一般的な形式を持っています-

Exp1 ? Exp2 : Exp3;

Exp1、Exp2、およびExp3は式です。 コロンの使用と配置に注意してください。

aの値 式は次のように決定されます。Exp1が評価されます。 真の場合、Exp2が評価され、?全体の値になります。 式です。 Exp1がfalseの場合、Exp3が評価され、その値が式の値になります。

C#-ループ

コードのブロックを数回実行する必要がある場合があります。 一般に、ステートメントは順番に実行されます。関数の最初のステートメントが最初に実行され、次に2番目のステートメントが実行されます。

プログラミング言語は、より複雑な実行パスを可能にするさまざまな制御構造を提供します。

ループステートメントは、ステートメントまたはステートメントのグループを複数回実行することを可能にし、次はほとんどのプログラミング言語のループステートメントの一般的なものです-

ループアーキテクチャ

C#は、ループ要件を処理するために次のタイプのループを提供します。 詳細を確認するには、次のリンクをクリックしてください。

Sr.No. Loop Type & Description
1

while loop

特定の条件が真である間、ステートメントまたはステートメントのグループを繰り返します。 ループ本体を実行する前に条件をテストします。

2

for loop

一連のステートメントを複数回実行し、ループ変数を管理するコードを省略します。

3

do…​while loop

whileステートメントに似ていますが、ループ本体の最後で条件をテストする点が異なります

4

nested loops

while、for、またはdo..whileループ内で1つ以上のループを使用できます。

ループ制御ステートメント

ループ制御ステートメントは、通常のシーケンスから実行を変更します。 実行がスコープを離れると、そのスコープで作成されたすべての自動オブジェクトが破棄されます。

C#は、次の制御ステートメントを提供します。 詳細を確認するには、次のリンクをクリックしてください。

Sr.No. Control Statement & Description
1

break statement

  • loop* または *switch* ステートメントを終了し、ループまたはスイッチの直後のステートメントに実行を転送します。
2

continue statement

ループがその本体の残りをスキップし、反復する前にその状態をすぐに再テストします。

無限ループ

条件が決して偽にならない場合、ループは無限ループになります。 for ループは伝統的にこの目的に使用されます。 forループを形成する3つの式はいずれも必要ないため、条件式を空のままにして無限ループを作成できます。

using System;

namespace Loops {
   class Program {
      static void Main(string[] args) {
         for (; ; ) {
            Console.WriteLine("Hey! I am Trapped");
         }
      }
   }
}

条件式が存在しない場合、trueと見なされます。 初期化および増分式を使用できますが、プログラマはより一般的にfor(;;)コンストラクトを使用して無限ループを示します。

C#-カプセル化

  • カプセル化*は、「物理または論理パッケージ内の1つ以上のアイテムを囲むプロセス」として定義されます。 オブジェクト指向プログラミングの方法論におけるカプセル化は、実装の詳細へのアクセスを防ぎます。

抽象化とカプセル化は、オブジェクト指向プログラミングの関連機能です。 抽象化により、関連情報を表示でき、カプセル化により、プログラマは「希望する抽象化レベルを実装する」ことができます。

カプセル化は、*アクセス指定子*を使用して実装されます。 *アクセス指定子*は、クラスメンバーのスコープと可視性を定義します。 C#は次のアクセス指定子をサポートしています-

  • パブリック
  • 非公開
  • 保護されています
  • 内部 *保護された内部

パブリックアクセス指定子

パブリックアクセス指定子を使用すると、クラスはそのメンバー変数とメンバー関数を他の関数とオブジェクトに公開できます。 すべてのパブリックメンバーは、クラスの外部からアクセスできます。

次の例はこれを示しています-

using System;

namespace RectangleApplication {
   class Rectangle {
     //member variables
      public double length;
      public double width;

      public double GetArea() {
         return length* width;
      }
      public void Display() {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle

   class ExecuteRectangle {
      static void Main(string[] args) {
         Rectangle r = new Rectangle();
         r.length = 4.5;
         r.width = 3.5;
         r.Display();
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Length: 4.5
Width: 3.5
Area: 15.75

前の例では、メンバー変数の長さと幅が public として宣言されているため、 r という名前のRectangleクラスのインスタンスを使用して、関数Main()からアクセスできます。

メンバー関数_Display()_および_GetArea()_は、クラスのインスタンスを使用せずにこれらの変数に直接アクセスすることもできます。

メンバー関数_Display()_も public として宣言されているため、 Main )から r という名前のRectangleクラスのインスタンスを使用してアクセスすることもできます。

プライベートアクセス指定子

プライベートアクセス指定子を使用すると、クラスはそのメンバー変数とメンバー関数を他の関数とオブジェクトから隠すことができます。 同じクラスの関数のみがそのプライベートメンバーにアクセスできます。 クラスのインスタンスでさえ、そのプライベートメンバーにアクセスできません。

次の例はこれを示しています-

using System;

namespace RectangleApplication {
   class Rectangle {
     //member variables
      private double length;
      private double width;

      public void Acceptdetails() {
         Console.WriteLine("Enter Length: ");
         length = Convert.ToDouble(Console.ReadLine());
         Console.WriteLine("Enter Width: ");
         width = Convert.ToDouble(Console.ReadLine());
      }
      public double GetArea() {
         return length * width;
      }
      public void Display() {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle

   class ExecuteRectangle {
      static void Main(string[] args) {
         Rectangle r = new Rectangle();
         r.Acceptdetails();
         r.Display();
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Enter Length:
4.4
Enter Width:
3.3
Length: 4.4
Width: 3.3
Area: 14.52

上記の例では、メンバー変数の長さと幅は private として宣言されているため、関数Main()からアクセスすることはできません。 メンバー関数_AcceptDetails()_および_Display()_はこれらの変数にアクセスできます。 メンバー関数_AcceptDetails()_および_Display()_は public として宣言されているため、 Main )から r という名前のRectangleクラスのインスタンスを使用してアクセスできます。

保護されたアクセス指定子

保護されたアクセス指定子により、子クラスはその基本クラスのメンバー変数とメンバー関数にアクセスできます。 これにより、継承の実装に役立ちます。 これについては、継承の章で詳しく説明します。

内部アクセス指定子

内部アクセス指定子により、クラスはそのメンバー変数とメンバー関数を現在のアセンブリ内の他の関数とオブジェクトに公開できます。 つまり、内部アクセス指定子を持つメンバーは、そのメンバーが定義されているアプリケーション内で定義されているクラスまたはメソッドからアクセスできます。

次のプログラムはこれを示しています-

using System;

namespace RectangleApplication {
   class Rectangle {
     //member variables
      internal double length;
      internal double width;

      double GetArea() {
         return length *width;
      }
      public void Display() {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle

   class ExecuteRectangle {
      static void Main(string[] args) {
         Rectangle r = new Rectangle();
         r.length = 4.5;
         r.width = 3.5;
         r.Display();
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Length: 4.5
Width: 3.5
Area: 15.75

上記の例では、メンバー関数_GetArea()_がアクセス指定子で宣言されていないことに注意してください。 次に、何も言及しない場合、クラスメンバーのデフォルトのアクセス指定子は何になりますか?* private *です。

保護された内部アクセス指定子

保護された内部アクセス指定子を使用すると、クラスは、同じアプリケーション内の子クラスを除き、他のクラスオブジェクトおよび関数からそのメンバー変数とメンバー関数を隠すことができます。 これは、継承を実装するときにも使用されます。

C#-メソッド

メソッドは、一緒にタスクを実行するステートメントのグループです。 すべてのC#プログラムには、Mainという名前のメソッドを持つクラスが少なくとも1つあります。

メソッドを使用するには、する必要があります-

  • メソッドを定義する
  • メソッドを呼び出す

C#でのメソッドの定義

メソッドを定義するとき、基本的にその構造の要素を宣言します。 C#でメソッドを定義するための構文は次のとおりです-

<Access Specifier> <Return Type> <Method Name>(Parameter List) {
   Method Body
}

以下は、メソッドのさまざまな要素です-

  • アクセス指定子-これは、変数または別のクラスのメソッドの可視性を決定します。
  • 戻り値の型-メソッドは値を返す場合があります。 戻り値の型は、メソッドが返す値のデータ型です。 メソッドが値を返さない場合、戻り値の型は void です。
  • メソッド名-メソッド名は一意の識別子であり、大文字と小文字が区別されます。 クラスで宣言されている他の識別子と同じにすることはできません。
  • パラメータリスト-括弧で囲まれたパラメータは、メソッドとのデータの受け渡しに使用されます。 パラメータリストは、メソッドのパラメータのタイプ、順序、および数を参照します。 パラメーターはオプションです。つまり、メソッドにパラメーターを含めることはできません。
  • メソッド本体-これには、必要なアクティビティを完了するために必要な一連の指示が含まれています。

次のコードスニペットは、2つの整数値を取り、2つのうち大きい方を返す関数_FindMax_を示しています。 パブリックアクセス指定子があるため、クラスのインスタンスを使用してクラスの外部からアクセスできます。

class NumberManipulator {

   public int FindMax(int num1, int num2) {
     /*local variable declaration*/
      int result;

      if (num1 > num2)
         result = num1;
      else
         result = num2;

      return result;
   }
   ...
}

C#でのメソッドの呼び出し

メソッドの名前を使用してメソッドを呼び出すことができます。 次の例はこれを示しています-

using System;

namespace CalculatorApplication {
   class NumberManipulator {
      public int FindMax(int num1, int num2) {
        /*local variable declaration*/
         int result;

         if (num1 > num2)
            result = num1;
         else
            result = num2;
         return result;
      }

      static void Main(string[] args) {
        /*local variable definition*/
         int a = 100;
         int b = 200;
         int ret;
         NumberManipulator n = new NumberManipulator();

        //calling the FindMax method
         ret = n.FindMax(a, b);
         Console.WriteLine("Max value is : {0}", ret );
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Max value is : 200

クラスのインスタンスを使用して、他のクラスからパブリックメソッドを呼び出すこともできます。 たとえば、メソッド_FindMax_は_NumberManipulator_クラスに属し、別のクラス_Test_から呼び出すことができます。

using System;

namespace CalculatorApplication {
   class NumberManipulator {
      public int FindMax(int num1, int num2) {
        /*local variable declaration*/
         int result;

         if(num1 > num2)
            result = num1;
         else
            result = num2;

         return result;
      }
   }
   class Test {
      static void Main(string[] args) {
        /*local variable definition*/
         int a = 100;
         int b = 200;
         int ret;
         NumberManipulator n = new NumberManipulator();

        //calling the FindMax method
         ret = n.FindMax(a, b);
         Console.WriteLine("Max value is : {0}", ret );
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Max value is : 200

再帰的なメソッド呼び出し

メソッドは自分自身を呼び出すことができます。 これは*再帰*と呼ばれます。 以下は、再帰関数を使用して、指定された数値の階乗を計算する例です-

using System;

namespace CalculatorApplication {
   class NumberManipulator {
      public int factorial(int num) {
        /*local variable declaration*/
         int result;
         if (num == 1) {
            return 1;
         } else {
            result = factorial(num - 1) * num;
            return result;
         }
      }
      static void Main(string[] args) {
         NumberManipulator n = new NumberManipulator();
        //calling the factorial method {0}", n.factorial(6));
         Console.WriteLine("Factorial of 7 is : {0}", n.factorial(7));
         Console.WriteLine("Factorial of 8 is : {0}", n.factorial(8));
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Factorial of 6 is: 720
Factorial of 7 is: 5040
Factorial of 8 is: 40320

メソッドにパラメーターを渡す

パラメータ付きのメソッドが呼び出されると、メソッドにパラメータを渡す必要があります。 パラメータをメソッドに渡すことができる3つの方法があります-

Sr.No. Mechanism & Description
1

Value parameters

このメソッドは、引数の実際の値を関数の仮パラメーターにコピーします。 この場合、関数内のパラメーターを変更しても、引数には影響しません。

2

Reference parameters

このメソッドは、引数のメモリ位置への参照を仮パラメータにコピーします。 これは、パラメーターに加えられた変更が引数に影響することを意味します。

3

Output parameters

このメソッドは、複数の値を返すのに役立ちます。

C#-Nullable

C#には nullable 型という特別なデータ型が用意されており、通常の値の範囲とnull値を割り当てることができます。

たとえば、-2,147,483,648から2,147,483,647までの任意の値またはNullable <Int32>変数にnullを格納できます。 同様に、Nullable <bool>変数にtrue、false、またはnullを割り当てることができます。 nullable 型を宣言するための構文は次のとおりです-

< data_type> ? <variable_name> = null;

次の例は、null許容データ型の使用を示しています-

using System;

namespace CalculatorApplication {
   class NullablesAtShow {
      static void Main(string[] args) {
         int? num1 = null;
         int? num2 = 45;

         double? num3 = new double?();
         double? num4 = 3.14157;

         bool? boolval = new bool?();

        //display the values
         Console.WriteLine("Nullables at Show: {0}, {1}, {2}, {3}", num1, num2, num3, num4);
         Console.WriteLine("A Nullable boolean value: {0}", boolval);
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Nullables at Show: , 45,  , 3.14157
A Nullable boolean value:

ヌル合体演算子(??)

null合体演算子は、null許容値型および参照型とともに使用されます。 これは、暗黙的な変換が可能な、オペランドを別のNULL入力可能(またはそうでない)値型オペランドの型に変換するために使用されます。

第1オペランドの値がNULLの場合、演算子は第2オペランドの値を返します。それ以外の場合、第1オペランドの値を返します。 次の例はこれを説明します-

using System;

namespace CalculatorApplication {
   class NullablesAtShow {
      static void Main(string[] args) {
         double? num1 = null;
         double? num2 = 3.14157;
         double num3;

         num3 = num1 ?? 5.34;
         Console.WriteLine(" Value of num3: {0}", num3);

         num3 = num2 ?? 5.34;
         Console.WriteLine(" Value of num3: {0}", num3);
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Value of num3: 5.34
Value of num3: 3.14157

C#-配列

配列には、同じタイプの要素の固定サイズの順次コレクションが格納されます。 配列はデータのコレクションを格納するために使用されますが、配列を連続したメモリ位置に格納された同じタイプの変数のコレクションと考える方が便利な場合があります。

number0、number1、…​、number99などの個々の変数を宣言する代わりに、numbersなどの1つの配列変数を宣言し、numbers [0]、numbers [1]、…​、numbers [99]を使用して表現します個々の変数。 配列内の特定の要素は、インデックスによってアクセスされます。

すべての配列は、連続したメモリ位置で構成されています。 最下位アドレスは最初の要素に対応し、最上位アドレスは最後の要素に対応します。

C#の配列

配列の宣言

C#で配列を宣言するには、次の構文を使用できます-

datatype[] arrayName;

どこで、

  • _datatype_は、配列内の要素のタイプを指定するために使用されます。
  • _ [] _は、配列のランクを指定します。 ランクは、配列のサイズを指定します。
  • _arrayName_は、配列の名前を指定します。

例えば、

double[] balance;

配列の初期化

配列を宣言しても、メモリ内の配列は初期化されません。 配列変数が初期化されると、配列に値を割り当てることができます。

配列は参照型であるため、 new キーワードを使用して配列のインスタンスを作成する必要があります。 例えば、

double[] balance = new double[10];

配列への値の割り当て

次のようなインデックス番号を使用して、個々の配列要素に値を割り当てることができます-

double[] balance = new double[10];
balance[0] = 4500.0;

あなたが示すように、宣言時に配列に値を割り当てることができます-

double[] balance = { 2340.0, 4523.69, 3421.0};

また、示されているように、配列を作成および初期化することができます-

int [] marks = new int[5]  { 99,  98, 92, 97, 95};

また、示されているように、配列のサイズを省略することができます-

int [] marks = new int[]  { 99,  98, 92, 97, 95};

配列変数を別のターゲット配列変数にコピーできます。 そのような場合、ターゲットとソースの両方が同じメモリ位置を指します-

int [] marks = new int[]  { 99,  98, 92, 97, 95};
int[] score = marks;

配列を作成すると、C#コンパイラは各配列要素を配列タイプに応じてデフォルト値に暗黙的に初期化します。 たとえば、int配列の場合、すべての要素は0に初期化されます。

配列要素へのアクセス

配列名にインデックスを付けることにより、要素にアクセスします。 これは、配列の名前の後に角かっこ内に要素のインデックスを配置することによって行われます。 例えば、

double salary = balance[9];

次の例は、上記の概念の宣言、割り当て、および配列へのアクセスを示しています-

using System;

namespace ArrayApplication {
   class MyArray {
      static void Main(string[] args) {
         int []  n = new int[10];/*n is an array of 10 integers*/
         int i,j;

        /*initialize elements of array n*/
         for ( i = 0; i < 10; i++ ) {
            n[ i ] = i + 100;
         }

        /*output each array element's value*/
         for (j = 0; j < 10; j++ ) {
            Console.WriteLine("Element[{0}] = {1}", j, n[j]);
         }
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109

_foreach_ループの使用

前の例では、各配列要素にアクセスするためにforループを使用しました。 foreach ステートメントを使用して、配列を反復処理することもできます。

using System;

namespace ArrayApplication {
   class MyArray {
      static void Main(string[] args) {
         int []  n = new int[10];/*n is an array of 10 integers*/

        /*initialize elements of array n*/
         for ( int i = 0; i < 10; i++ ) {
            n[i] = i + 100;
         }

        /*output each array element's value*/
         foreach (int j in n ) {
            int i = j-100;
            Console.WriteLine("Element[{0}] = {1}", i, j);
         }
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Element[0] = 100
Element[1] = 101
Element[2] = 102
Element[3] = 103
Element[4] = 104
Element[5] = 105
Element[6] = 106
Element[7] = 107
Element[8] = 108
Element[9] = 109

C#配列

C#プログラマーに明らかな配列に関連するいくつかの重要な概念があります-

Sr.No. Concept & Description
1

Multi-dimensional arrays

C#は多次元配列をサポートしています。 多次元配列の最も単純な形式は、2次元配列です。

2

Jagged arrays

C#は、配列の配列である多次元配列をサポートしています。

3

Passing arrays to functions

インデックスなしで配列の名前を指定することで、関数に配列へのポインタを渡すことができます。

4

Param arrays

これは、不明な数のパラメーターを関数に渡すために使用されます。

5

The Array Class

System名前空間で定義され、すべての配列の基本クラスであり、配列を操作するためのさまざまなプロパティとメソッドを提供します。

C#-文字列

C#では、文字列を文字の配列として使用できますが、より一般的な方法は、 string キーワードを使用して文字列変数を宣言することです。 文字列キーワードは、 System.String クラスのエイリアスです。

文字列オブジェクトの作成

次の方法のいずれかを使用して文字列オブジェクトを作成できます-

  • 文字列リテラルを文字列変数に割り当てることにより
  • Stringクラスコンストラクターを使用して
  • 文字列連結演算子(+)を使用する
  • プロパティを取得するか、文字列を返すメソッドを呼び出すことにより *書式設定メソッドを呼び出して、値またはオブジェクトを文字列表現に変換する

次の例はこれを示しています-

using System;

namespace StringApplication {

   class Program {

      static void Main(string[] args) {
        //from string literal and string concatenation
         string fname, lname;
         fname = "Rowan";
         lname = "Atkinson";

         char []letters= { 'H', 'e', 'l', 'l','o' };
         string [] sarray={ "Hello", "From", "Tutorials", "Point" };

         string fullname = fname + lname;
         Console.WriteLine("Full Name: {0}", fullname);

        //by using string constructor { 'H', 'e', 'l', 'l','o' };
         string greetings = new string(letters);
         Console.WriteLine("Greetings: {0}", greetings);

        //methods returning string { "Hello", "From", "Tutorials", "Point" };
         string message = String.Join(" ", sarray);
         Console.WriteLine("Message: {0}", message);

        //formatting method to convert a value
         DateTime waiting = new DateTime(2012, 10, 10, 17, 58, 1);
         string chat = String.Format("Message sent at {0:t} on {0:D}", waiting);
         Console.WriteLine("Message: {0}", chat);
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Full Name: RowanAtkinson
Greetings: Hello
Message: Hello From Tutorials Point
Message: Message sent at 5:58 PM on Wednesday, October 10, 2012

文字列クラスのプロパティ

文字列クラスには、次の2つのプロパティがあります-

Sr.No. Property & Description
1
  • Chars*

現在の_String_オブジェクトの指定された位置にある_Char_オブジェクトを取得します。

2

Length

現在のStringオブジェクトの文字数を取得します。

Stringクラスのメソッド

Stringクラスには、文字列オブジェクトの操作に役立つ多数のメソッドがあります。 次の表は、最も一般的に使用される方法のいくつかを提供します-

以下に、Stringクラスのメソッドのリストを示します。

Sr.No. Methods & Description
1

public static int Compare(string strA, string strB)

指定した2つの文字列オブジェクトを比較し、並べ替え順序での相対的な位置を示す整数を返します。

2

public static int Compare(string strA, string strB, bool ignoreCase )

指定した2つの文字列オブジェクトを比較し、並べ替え順序での相対的な位置を示す整数を返します。 ただし、ブール値パラメーターがtrueの場合、大文字と小文字は無視されます。

3

public static string Concat(string str0, string str1)

2つの文字列オブジェクトを連結します。

4

public static string Concat(string str0, string str1, string str2)

3つの文字列オブジェクトを連結します。

5

public static string Concat(string str0, string str1, string str2, string str3)

4つの文字列オブジェクトを連結します。

6

public bool Contains(string value)

指定されたStringオブジェクトがこの文字列内で発生するかどうかを示す値を返します。

7

public static string Copy(string str)

指定された文字列と同じ値を持つ新しいStringオブジェクトを作成します。

8

public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)

Stringオブジェクトの指定された位置からUnicode文字の配列内の指定された位置に、指定された数の文字をコピーします。

9

public bool EndsWith(string value)

文字列オブジェクトの末尾が指定された文字列と一致するかどうかを判断します。

10

public bool Equals(string value)

現在のStringオブジェクトと指定されたStringオブジェクトが同じ値を持つかどうかを決定します。

11

public static bool Equals(string a, string b)

指定した2つのStringオブジェクトの値が同じかどうかを判断します。

12

public static string Format(string format, Object arg0)

指定された文字列内の1つ以上の書式項目を、指定されたオブジェクトの文字列表現に置き換えます。

13

public int IndexOf(char value)

現在の文字列で指定されたUnicode文字が最初に出現するゼロから始まるインデックスを返します。

14

public int IndexOf(string value)

このインスタンスで指定された文字列が最初に出現するゼロから始まるインデックスを返します。

15

public int IndexOf(char value, int startIndex)

指定された文字位置で検索を開始し、この文字列で指定されたUnicode文字が最初に出現するゼロから始まるインデックスを返します。

16

public int IndexOf(string value, int startIndex)

指定された文字位置で検索を開始し、このインスタンスで指定された文字列が最初に出現するゼロから始まるインデックスを返します。

17

public int IndexOfAny(char[] anyOf)

Unicode文字の指定された配列内の任意の文字のこのインスタンスでの最初の出現のゼロから始まるインデックスを返します。

18

public int IndexOfAny(char[] anyOf, int startIndex)

指定されたUnicode文字の配列内の任意の文字のこのインスタンスでの最初の出現のゼロから始まるインデックスを返し、指定された文字位置で検索を開始します。

19

public string Insert(int startIndex, string value)

現在の文字列オブジェクトの指定されたインデックス位置に指定された文字列が挿入された新しい文字列を返します。

20

public static bool IsNullOrEmpty(string value)

指定された文字列がnullか空の文字列かを示します。

21

public static string Join(string separator, params string[] value)

各要素間に指定されたセパレータを使用して、文字列配列のすべての要素を連結します。

22

public static string Join(string separator, string[] value, int startIndex, int count)

各要素間に指定された区切り文字を使用して、文字列配列の指定された要素を連結します。

23

public int LastIndexOf(char value)

現在の文字列オブジェクト内で指定されたUnicode文字が最後に出現するゼロから始まるインデックス位置を返します。

24

public int LastIndexOf(string value)

現在の文字列オブジェクト内で指定された文字列が最後に出現するゼロから始まるインデックス位置を返します。

25

public string Remove(int startIndex)

指定された位置から始まり、最後の位置まで続く現在のインスタンスのすべての文字を削除し、文字列を返します。

26

public string Remove(int startIndex, int count)

指定された位置から始まる現在の文字列の指定された文字数を削除し、文字列を返します。

27

public string Replace(char oldChar, char newChar)

現在の文字列オブジェクト内の指定されたUnicode文字のすべての出現を指定されたUnicode文字で置き換え、新しい文字列を返します。

28

public string Replace(string oldValue, string newValue)

現在の文字列オブジェクト内の指定された文字列のすべての出現を指定された文字列で置き換え、新しい文字列を返します。

29

public string[] Split(params char[] separator)

指定されたUnicode文字配列の要素で区切られた、現在の文字列オブジェクトの部分文字列を含む文字配列を返します。

30

public string[] Split(char[] separator, int count)

指定されたUnicode文字配列の要素で区切られた、現在の文字列オブジェクトの部分文字列を含む文字配列を返します。 intパラメーターは、返される部分文字列の最大数を指定します。

31

public bool StartsWith(string value)

この文字列インスタンスの先頭が指定した文字列と一致するかどうかを判断します。

32

public char[] ToCharArray()

現在の文字列オブジェクト内のすべての文字を含むUnicode文字配列を返します。

33

public char[] ToCharArray(int startIndex, int length)

指定されたインデックスから指定された長さまでの、現在の文字列オブジェクト内のすべての文字を含むUnicode文字配列を返します。

34

public string ToLower()

この文字列のコピーを小文字に変換して返します。

35

public string ToUpper()

この文字列のコピーを大文字に変換して返します。

36

public string Trim()

現在のStringオブジェクトから先頭および末尾の空白文字をすべて削除します。

メソッドとStringクラスコンストラクターの完全なリストについては、MSDNライブラリをご覧ください。

次の例は、上記の方法のいくつかを示しています-

文字列の比較

using System;

namespace StringApplication {

   class StringProg {

      static void Main(string[] args) {
         string str1 = "This is test";
         string str2 = "This is text";

         if (String.Compare(str1, str2) == 0) {
            Console.WriteLine(str1 + " and " + str2 +  " are equal.");
         } else {
            Console.WriteLine(str1 + " and " + str2 + " are not equal.");
         }
         Console.ReadKey() ;
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

This is test and This is text are not equal.

文字列には文字列が含まれます

using System;

namespace StringApplication {

   class StringProg {

      static void Main(string[] args) {
         string str = "This is test";

         if (str.Contains("test")) {
            Console.WriteLine("The sequence 'test' was found.");
         }
         Console.ReadKey() ;
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

The sequence 'test' was found.

部分文字列を取得する

using System;

namespace StringApplication {

   class StringProg {

      static void Main(string[] args) {
         string str = "Last night I dreamt of San Pedro";
         Console.WriteLine(str);
         string substr = str.Substring(23);
         Console.WriteLine(substr);
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

San Pedro

文字列の結合

using System;

namespace StringApplication {

   class StringProg {

      static void Main(string[] args) {
         string[] starray = new string[]{"Down the way nights are dark",
            "And the sun shines daily on the mountain top",
            "I took a trip on a sailing ship",
            "And when I reached Jamaica",
            "I made a stop"};

         string str = String.Join("\n", starray);
         Console.WriteLine(str);
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Down the way nights are dark
And the sun shines daily on the mountain top
I took a trip on a sailing ship
And when I reached Jamaica
I made a stop

C#-構造

C#では、構造体は値型のデータ型です。 さまざまなデータ型の関連データを保持する単一の変数を作成するのに役立ちます。 struct キーワードは、構造の作成に使用されます。

構造は、レコードを表すために使用されます。 図書館で本を追跡したいとします。 あなたは、各本に関する次の属性を追跡することができます-

  • タイトル
  • 著者
  • 件名
  • ブックID

構造の定義

構造を定義するには、structステートメントを使用する必要があります。 structステートメントは、プログラムに複数のメンバーを持つ新しいデータ型を定義します。

たとえば、これはあなたが本の構造を宣言することができる方法です-

struct Books {
   public string title;
   public string author;
   public string subject;
   public int book_id;
};

次のプログラムは、構造の使用を示しています-

using System;

struct Books {
   public string title;
   public string author;
   public string subject;
   public int book_id;
};

public class testStructure {
   public static void Main(string[] args) {
      Books Book1;  /*Declare Book1 of type Book*/
      Books Book2;  /*Declare Book2 of type Book*/

     /*book 1 specification*/
      Book1.title = "C Programming";
      Book1.author = "Nuha Ali";
      Book1.subject = "C Programming Tutorial";
      Book1.book_id = 6495407;

     /*book 2 specification*/
      Book2.title = "Telecom Billing";
      Book2.author = "Zara Ali";
      Book2.subject =  "Telecom Billing Tutorial";
      Book2.book_id = 6495700;

     /*print Book1 info*/
      Console.WriteLine( "Book 1 title : {0}", Book1.title);
      Console.WriteLine("Book 1 author : {0}", Book1.author);
      Console.WriteLine("Book 1 subject : {0}", Book1.subject);
      Console.WriteLine("Book 1 book_id :{0}", Book1.book_id);

     /*print Book2 info*/
      Console.WriteLine("Book 2 title : {0}", Book2.title);
      Console.WriteLine("Book 2 author : {0}", Book2.author);
      Console.WriteLine("Book 2 subject : {0}", Book2.subject);
      Console.WriteLine("Book 2 book_id : {0}", Book2.book_id);

      Console.ReadKey();
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700

C#構造の機能

Booksという名前の単純な構造を既に使用しています。 C#の構造は、従来のCまたはC ++の構造とはまったく異なります。 C#の構造には、次の機能があります-

  • 構造には、メソッド、フィールド、インデクサー、プロパティ、演算子メソッド、およびイベントを含めることができます。
  • 構造体にはコンストラクターを定義できますが、デストラクタはできません。 ただし、構造体の既定のコンストラクターを定義することはできません。 デフォルトのコンストラクターは自動的に定義され、変更できません。
  • クラスとは異なり、構造体は他の構造体またはクラスを継承できません。
  • 構造は、他の構造またはクラスのベースとして使用できません。
  • 構造体は、1つ以上のインターフェースを実装できます。
  • 構造メンバーは、抽象、仮想、または保護として指定できません。
  • New 演算子を使用してstructオブジェクトを作成すると、作成され、適切なコンストラクターが呼び出されます。 クラスとは異なり、構造体はNew演算子を使用せずにインスタンス化できます。
  • New演算子を使用しない場合、フィールドは未割り当てのままで、すべてのフィールドが初期化されるまでオブジェクトを使用できません。

クラスと構造

クラスと構造には、次の基本的な違いがあります-

  • クラスは参照型であり、構造体は値型です
  • 構造は継承をサポートしていません
  • 構造体にデフォルトのコンストラクターを含めることはできません

上記の議論に照らして、前の例を書き換えましょう-

using System;

struct Books {
   private string title;
   private string author;
   private string subject;
   private int book_id;

   public void getValues(string t, string a, string s, int id) {
      title = t;
      author = a;
      subject = s;
      book_id = id;
   }

   public void display() {
      Console.WriteLine("Title : {0}", title);
      Console.WriteLine("Author : {0}", author);
      Console.WriteLine("Subject : {0}", subject);
      Console.WriteLine("Book_id :{0}", book_id);
   }
};

public class testStructure {

   public static void Main(string[] args) {
      Books Book1 = new Books();  /*Declare Book1 of type Book*/
      Books Book2 = new Books();  /*Declare Book2 of type Book*/

     /*book 1 specification*/
      Book1.getValues("C Programming",
      "Nuha Ali", "C Programming Tutorial",6495407);

     /*book 2 specification*/
      Book2.getValues("Telecom Billing",
      "Zara Ali", "Telecom Billing Tutorial", 6495700);

     /*print Book1 info*/
      Book1.display();

     /*print Book2 info*/
      Book2.display();

      Console.ReadKey();
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Title : C Programming
Author : Nuha Ali
Subject : C Programming Tutorial
Book_id : 6495407
Title : Telecom Billing
Author : Zara Ali
Subject : Telecom Billing Tutorial
Book_id : 6495700

C#-列挙

列挙は、名前付き整数定数のセットです。 列挙型は、 enum キーワードを使用して宣言されます。

C#列挙は値のデータ型です。 つまり、列挙には独自の値が含まれており、継承することも継承することもできません。

_enum_変数の宣言

列挙を宣言するための一般的な構文は次のとおりです-

enum <enum_name> {
   enumeration list
};

どこで、

  • _enum_name_は、列挙型の名前を指定します。
  • _enumeration list_は、識別子のコンマ区切りリストです。

列挙リスト内の各シンボルは整数値を表し、その前のシンボルよりも1つ大きくなります。 デフォルトでは、最初の列挙シンボルの値は0です。 たとえば-

enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };

次の例は、列挙型変数の使用方法を示しています-

using System;

namespace EnumApplication {
   class EnumProgram {
      enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };

      static void Main(string[] args) {
         int WeekdayStart = (int)Days.Mon;
         int WeekdayEnd = (int)Days.Fri;

         Console.WriteLine("Monday: {0}", WeekdayStart);
         Console.WriteLine("Friday: {0}", WeekdayEnd);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Monday: 1
Friday: 5

C#-クラス

クラスを定義するときには、データ型の設計図を定義します。 これは実際にはデータを定義しませんが、クラス名の意味を定義します。 つまり、クラスのオブジェクトの構成要素と、そのオブジェクトに対して実行できる操作。 オブジェクトはクラスのインスタンスです。 クラスを構成するメソッドと変数は、クラスのメンバーと呼ばれます。

クラスを定義する

クラス定義は、キーワードclassで始まり、その後にクラス名が続きます。クラス本体は、中括弧のペアで囲まれています。 以下は、クラス定義の一般的な形式です-

<access specifier> class  class_name {
  //member variables
   <access specifier> <data type> variable1;
   <access specifier> <data type> variable2;
   ...
   <access specifier> <data type> variableN;
  //member methods
   <access specifier> <return type> method1(parameter_list) {
     //method body
   }
   <access specifier> <return type> method2(parameter_list) {
     //method body
   }
   ...
   <access specifier> <return type> methodN(parameter_list) {
     //method body
   }
}

注-

  • アクセス指定子は、メンバーとクラス自体のアクセス規則を指定します。 言及されていない場合、クラス型のデフォルトのアクセス指定子は internal です。 メンバーのデフォルトアクセスは private です。
  • データ型は変数の型を指定し、戻り値の型はメソッドが返すデータのデータ型があればそれを指定します。
  • クラスメンバにアクセスするには、ドット(。)演算子を使用します。 *ドット演算子は、オブジェクトの名前をメンバーの名前にリンクします。

次の例は、これまでに説明した概念を示しています-

using System;

namespace BoxApplication {
   class Box {
      public double length;  //Length of a box
      public double breadth; //Breadth of a box
      public double height;  //Height of a box
   }
   class Boxtester {
      static void Main(string[] args) {
         Box Box1 = new Box();  //Declare Box1 of type Box
         Box Box2 = new Box();  //Declare Box2 of type Box
         double volume = 0.0;   //Store the volume of a box here

        //box 1 specification
         Box1.height = 5.0;
         Box1.length = 6.0;
         Box1.breadth = 7.0;

        //box 2 specification
         Box2.height = 10.0;
         Box2.length = 12.0;
         Box2.breadth = 13.0;

        //volume of box 1
         volume = Box1.height* Box1.length *Box1.breadth;
         Console.WriteLine("Volume of Box1 : {0}",  volume);

        //volume of box 2
         volume = Box2.height* Box2.length *Box2.breadth;
         Console.WriteLine("Volume of Box2 : {0}", volume);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Volume of Box1 : 210
Volume of Box2 : 1560

メンバー関数とカプセル化

クラスのメンバー関数は、他の変数と同様に、クラス定義内に定義またはプロトタイプを持つ関数です。 メンバーであるクラスのオブジェクトを操作し、そのオブジェクトのクラスのすべてのメンバーにアクセスできます。

メンバー変数は(設計の観点から)オブジェクトの属性であり、カプセル化を実装するためにプライベートに保持されます。 これらの変数は、パブリックメンバー関数を使用してのみアクセスできます。

クラス内の異なるクラスメンバーの値を設定および取得するための上記の概念を入れてみましょう-

using System;

namespace BoxApplication {
   class Box {
      private double length;  //Length of a box
      private double breadth; //Breadth of a box
      private double height;  //Height of a box

      public void setLength( double len ) {
         length = len;
      }
      public void setBreadth( double bre ) {
         breadth = bre;
      }
      public void setHeight( double hei ) {
         height = hei;
      }
      public double getVolume() {
         return length* breadth * height;
      }
   }
   class Boxtester {
      static void Main(string[] args) {
         Box Box1 = new Box();  //Declare Box1 of type Box
         Box Box2 = new Box();
         double volume;

        //Declare Box2 of type Box
        //box 1 specification
         Box1.setLength(6.0);
         Box1.setBreadth(7.0);
         Box1.setHeight(5.0);

        //box 2 specification
         Box2.setLength(12.0);
         Box2.setBreadth(13.0);
         Box2.setHeight(10.0);

        //volume of box 1
         volume = Box1.getVolume();
         Console.WriteLine("Volume of Box1 : {0}" ,volume);

        //volume of box 2
         volume = Box2.getVolume();
         Console.WriteLine("Volume of Box2 : {0}", volume);

         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Volume of Box1 : 210
Volume of Box2 : 1560

C#コンストラクター

クラス*コンストラクタ*は、そのクラスの新しいオブジェクトを作成するたびに実行されるクラスの特別なメンバー関数です。

コンストラクターはクラスの名前とまったく同じ名前を持ち、戻り値の型はありません。 次の例では、コンストラクタの概念を説明します-

using System;

namespace LineApplication {
   class Line {
      private double length;  //Length of a line

      public Line() {
         Console.WriteLine("Object is being created");
      }
      public void setLength( double len ) {
         length = len;
      }
      public double getLength() {
         return length;
      }

      static void Main(string[] args) {
         Line line = new Line();

        //set line length
         line.setLength(6.0);
         Console.WriteLine("Length of line : {0}", line.getLength());
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Object is being created
Length of line : 6
  • デフォルトのコンストラクタ*にはパラメータがありませんが、必要に応じて、コンストラクタにパラメータを含めることができます。 このようなコンストラクターは、*パラメーター化されたコンストラクター*と呼ばれます。 この手法は、次の例に示すように、作成時にオブジェクトに初期値を割り当てるのに役立ちます-
using System;

namespace LineApplication {
   class Line {
      private double length;  //Length of a line

      public Line(double len) { //Parameterized constructor
         Console.WriteLine("Object is being created, length = {0}", len);
         length = len;
      }
      public void setLength( double len ) {
         length = len;
      }
      public double getLength() {
         return length;
      }
      static void Main(string[] args) {
         Line line = new Line(10.0);
         Console.WriteLine("Length of line : {0}", line.getLength());

        //set line length
         line.setLength(6.0);
         Console.WriteLine("Length of line : {0}", line.getLength());
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Object is being created, length = 10
Length of line : 10
Length of line : 6

C#デストラクタ

  • デストラクタ*は、クラスのオブジェクトがスコープ外に出るたびに実行されるクラスの特別なメンバー関数です。 *デストラクタ*は、チルダ(〜)が前に付いたクラスとまったく同じ名前を持ち、値を返すことも、パラメータを取ることもできません。

デストラクタは、プログラムを終了する前にメモリリソースを解放するのに非常に役立ちます。 デストラクタは継承またはオーバーロードできません。

次の例では、デストラクタの概念を説明します-

using System;

namespace LineApplication {
   class Line {
      private double length;  //Length of a line

      public Line() {  //constructor
         Console.WriteLine("Object is being created");
      }
      ~Line() {  //destructor
         Console.WriteLine("Object is being deleted");
      }
      public void setLength( double len ) {
         length = len;
      }
      public double getLength() {
         return length;
      }
      static void Main(string[] args) {
         Line line = new Line();

        //set line length
         line.setLength(6.0);
         Console.WriteLine("Length of line : {0}", line.getLength());
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Object is being created
Length of line : 6
Object is being deleted

C#クラスの静的メンバー

*static* キーワードを使用して、クラスメンバーを静的として定義できます。 クラスのメンバーを静的として宣言する場合、クラスのオブジェクトがいくつ作成されても、静的メンバーのコピーは1つしかありません。

キーワード static は、クラスに対してメンバーのインスタンスが1つだけ存在することを意味します。 静的変数は、クラスのインスタンスを作成せずにクラスを呼び出すことで値を取得できるため、定数の定義に使用されます。 静的変数は、メンバー関数またはクラス定義の外部で初期化できます。 クラス定義内の静的変数を初期化することもできます。

次の例は、*静的変数*の使用を示しています-

using System;

namespace StaticVarApplication {
   class StaticVar {
      public static int num;

      public void count() {
         num++;
      }
      public int getNum() {
         return num;
      }
   }
   class StaticTester {
      static void Main(string[] args) {
         StaticVar s1 = new StaticVar();
         StaticVar s2 = new StaticVar();

         s1.count();
         s1.count();
         s1.count();

         s2.count();
         s2.count();
         s2.count();

         Console.WriteLine("Variable num for s1: {0}", s1.getNum());
         Console.WriteLine("Variable num for s2: {0}", s2.getNum());
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Variable num for s1: 6
Variable num for s2: 6
  • メンバー関数*を*静的*として宣言することもできます。 このような関数は、静的変数にのみアクセスできます。 静的関数は、オブジェクトが作成される前でも存在します。 次の例は、*静的関数*の使用を示しています-
using System;

namespace StaticVarApplication {
   class StaticVar {
      public static int num;

      public void count() {
         num++;
      }
      public static int getNum() {
         return num;
      }
   }
   class StaticTester {
      static void Main(string[] args) {
         StaticVar s = new StaticVar();

         s.count();
         s.count();
         s.count();

         Console.WriteLine("Variable num: {0}", StaticVar.getNum());
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Variable num: 3

C#-継承

オブジェクト指向プログラミングで最も重要な概念の1つは継承です。 継承を使用すると、クラスを別のクラスの観点から定義でき、アプリケーションの作成と保守が簡単になります。 これは、コード機能を再利用する機会を提供し、実装時間を短縮します。

クラスを作成するとき、プログラマは完全に新しいデータメンバーとメンバー関数を記述する代わりに、新しいクラスが既存のクラスのメンバーを継承するように指定できます。 この既存のクラスは base クラスと呼ばれ、新しいクラスは derived クラスと呼ばれます。

継承のアイデアは、 IS-A 関係を実装します。 たとえば、哺乳類 IS A 動物、犬 IS-A 哺乳類、したがって犬 IS-A 動物などです。

基本クラスと派生クラス

クラスは複数のクラスまたはインターフェイスから派生できます。つまり、複数の基本クラスまたはインターフェイスからデータと機能を継承できます。

派生クラスを作成するためにC#で使用される構文は次のとおりです-

<acess-specifier> class <base_class> {
   ...
}

class <derived_class> : <base_class> {
   ...
}

基本クラスShapeとその派生クラスRectangleを考えます-

using System;

namespace InheritanceApplication {
   class Shape {
      public void setWidth(int w) {
         width = w;
      }
      public void setHeight(int h) {
         height = h;
      }
      protected int width;
      protected int height;
   }

  //Derived class
   class Rectangle: Shape {
      public int getArea() {
         return (width *height);
      }
   }
   class RectangleTester {
      static void Main(string[] args) {
         Rectangle Rect = new Rectangle();

         Rect.setWidth(5);
         Rect.setHeight(7);

        //Print the area of the object.
         Console.WriteLine("Total area: {0}",  Rect.getArea());
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Total area: 35

基本クラスの初期化

派生クラスは、基本クラスのメンバー変数とメンバーメソッドを継承します。 したがって、サブクラスを作成する前に、スーパークラスオブジェクトを作成する必要があります。 メンバーの初期化リストで、スーパークラスの初期化の指示を与えることができます。

次のプログラムはこれを示しています-

using System;

namespace RectangleApplication {
   class Rectangle {

     //member variables
      protected double length;
      protected double width;

      public Rectangle(double l, double w) {
         length = l;
         width = w;
      }
      public double GetArea() {
         return length* width;
      }
      public void Display() {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle
   class Tabletop : Rectangle {
      private double cost;
      public Tabletop(double l, double w) : base(l, w) { }

      public double GetCost() {
         double cost;
         cost = GetArea() * 70;
         return cost;
      }
      public void Display() {
         base.Display();
         Console.WriteLine("Cost: {0}", GetCost());
      }
   }
   class ExecuteRectangle {
      static void Main(string[] args) {
         Tabletop t = new Tabletop(4.5, 7.5);
         t.Display();
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Length: 4.5
Width: 7.5
Area: 33.75
Cost: 2362.5

C#での多重継承

  • C#は多重継承をサポートしていません*。 ただし、インターフェイスを使用して複数の継承を実装できます。 次のプログラムはこれを示しています-
using System;

namespace InheritanceApplication {
   class Shape {
      public void setWidth(int w) {
         width = w;
      }
      public void setHeight(int h) {
         height = h;
      }
      protected int width;
      protected int height;
   }

  //Base class PaintCost
   public interface PaintCost {
      int getCost(int area);
   }

  //Derived class
   class Rectangle : Shape, PaintCost {
      public int getArea() {
         return (width *height);
      }
      public int getCost(int area) {
         return area* 70;
      }
   }
   class RectangleTester {
      static void Main(string[] args) {
         Rectangle Rect = new Rectangle();
         int area;

         Rect.setWidth(5);
         Rect.setHeight(7);
         area = Rect.getArea();

        //Print the area of the object.
         Console.WriteLine("Total area: {0}",  Rect.getArea());
         Console.WriteLine("Total paint cost: ${0}" , Rect.getCost(area));
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Total area: 35
Total paint cost: $2450

C#-ポリモーフィズム

「多態性」という言葉は、多くの形式を持つことを意味します。 オブジェクト指向プログラミングのパラダイムでは、多態性は「1つのインターフェイス、複数の機能」として表現されることがよくあります。

多態性は静的または動的です。 static polymorphism では、関数への応答はコンパイル時に決定されます。 *動的なポリモーフィズム*では、実行時に決定されます。

静的多型

コンパイル時に関数をオブジェクトにリンクするメカニズムは、事前バインディングと呼ばれます。 静的バインディングとも呼ばれます。 C#は、静的なポリモーフィズムを実装する2つの手法を提供します。 彼らは-

  • 関数オーバーロード
  • オペレータの過負荷

次の章で演算子のオーバーロードについて説明します。

関数のオーバーロード

同じスコープ内で同じ関数名に複数の定義を設定できます。 関数の定義は、引数リスト内の引数のタイプまたは数、あるいはその両方によって互いに異なる必要があります。 戻り型のみが異なる関数宣言をオーバーロードすることはできません。

次の例は、関数* print()*を使用してさまざまなデータ型を印刷することを示しています-

using System;

namespace PolymorphismApplication {
   class Printdata {
      void print(int i) {
         Console.WriteLine("Printing int: {0}", i );
      }
      void print(double f) {
         Console.WriteLine("Printing float: {0}" , f);
      }
      void print(string s) {
         Console.WriteLine("Printing string: {0}", s);
      }
      static void Main(string[] args) {
         Printdata p = new Printdata();

        //Call print to print integer
         p.print(5);

        //Call print to print float
         p.print(500.263);

        //Call print to print string
         p.print("Hello C++");
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Printing int: 5
Printing float: 500.263
Printing string: Hello C++

動的多型

C#では、インターフェイスの部分クラス実装を提供するために使用される抽象クラスを作成できます。 派生クラスがそれを継承すると、実装が完了します。 Abstract クラスには、派生クラスによって実装される抽象メソッドが含まれています。 派生クラスには、より専門的な機能があります。

抽象クラスに関するルールは次のとおりです-

  • 抽象クラスのインスタンスを作成することはできません
  • 抽象クラスの外部で抽象メソッドを宣言することはできません
  • クラスが sealed として宣言されている場合、そのクラスを継承することはできず、抽象クラスをsealedとして宣言することはできません。

次のプログラムは、抽象クラスを示しています-

using System;

namespace PolymorphismApplication {
   abstract class Shape {
      public abstract int area();
   }

   class Rectangle:  Shape {
      private int length;
      private int width;

      public Rectangle( int a = 0, int b = 0) {
         length = a;
         width = b;
      }
      public override int area () {
         Console.WriteLine("Rectangle class area :");
         return (width * length);
      }
   }
   class RectangleTester {
      static void Main(string[] args) {
         Rectangle r = new Rectangle(10, 7);
         double a = r.area();
         Console.WriteLine("Area: {0}",a);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Rectangle class area :
Area: 70

継承されたクラスに実装するクラスで定義された関数がある場合、*仮想*関数を使用します。 仮想関数は、継承されたクラスごとに異なる方法で実装でき、これらの関数の呼び出しは実行時に決定されます。

ダイナミックポリモーフィズムは、*抽象クラス*および*仮想関数*によって実装されます。

次のプログラムはこれを示しています-

using System;

namespace PolymorphismApplication {
   class Shape {
      protected int width, height;

      public Shape( int a = 0, int b = 0) {
         width = a;
         height = b;
      }
      public virtual int area() {
         Console.WriteLine("Parent class area :");
         return 0;
      }
   }
   class Rectangle: Shape {
      public Rectangle( int a = 0, int b = 0): base(a, b) {

      }
      public override int area () {
         Console.WriteLine("Rectangle class area :");
         return (width *height);
      }
   }
   class Triangle: Shape {
      public Triangle(int a = 0, int b = 0): base(a, b) {
      }
      public override int area() {
         Console.WriteLine("Triangle class area :");
         return (width* height/2);
      }
   }
   class Caller {
      public void CallArea(Shape sh) {
         int a;
         a = sh.area();
         Console.WriteLine("Area: {0}", a);
      }
   }
   class Tester {
      static void Main(string[] args) {
         Caller c = new Caller();
         Rectangle r = new Rectangle(10, 7);
         Triangle t = new Triangle(10, 5);

         c.CallArea(r);
         c.CallArea(t);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Rectangle class area:
Area: 70
Triangle class area:
Area: 25

C#-オペレーターのオーバーロード

C#で使用可能なほとんどの組み込み演算子を再定義またはオーバーロードできます。 したがって、プログラマはユーザー定義型の演算子も使用できます。 オーバーロードされた演算子は、キーワード operator の後に定義される演算子の記号が続く特別な名前を持つ関数です。 他の関数と同様に、オーバーロードされた演算子には戻り値の型とパラメーターリストがあります。

たとえば、次の機能を通過します-

public static Box operator+ (Box b, Box c) {
   Box box = new Box();
   box.length = b.length + c.length;
   box.breadth = b.breadth + c.breadth;
   box.height = b.height + c.height;
   return box;
}

上記の関数は、ユーザー定義クラスBoxの加算演算子(+)を実装しています。 2つのBoxオブジェクトの属性を追加し、結果のBoxオブジェクトを返します。

オペレーターのオーバーロードの実装

次のプログラムは、完全な実装を示しています-

using System;

namespace OperatorOvlApplication {
   class Box {
      private double length;  //Length of a box
      private double breadth; //Breadth of a box
      private double height;  //Height of a box

      public double getVolume() {
         return length *breadth* height;
      }
      public void setLength( double len ) {
         length = len;
      }
      public void setBreadth( double bre ) {
         breadth = bre;
      }
      public void setHeight( double hei ) {
         height = hei;
      }

     //Overload + operator to add two Box objects.
      public static Box operator+ (Box b, Box c) {
         Box box = new Box();
         box.length = b.length + c.length;
         box.breadth = b.breadth + c.breadth;
         box.height = b.height + c.height;
         return box;
      }
   }
   class Tester {
      static void Main(string[] args) {
         Box Box1 = new Box();  //Declare Box1 of type Box
         Box Box2 = new Box();  //Declare Box2 of type Box
         Box Box3 = new Box();  //Declare Box3 of type Box
         double volume = 0.0;   //Store the volume of a box here

        //box 1 specification
         Box1.setLength(6.0);
         Box1.setBreadth(7.0);
         Box1.setHeight(5.0);

        //box 2 specification
         Box2.setLength(12.0);
         Box2.setBreadth(13.0);
         Box2.setHeight(10.0);

        //volume of box 1
         volume = Box1.getVolume();
         Console.WriteLine("Volume of Box1 : {0}", volume);

        //volume of box 2
         volume = Box2.getVolume();
         Console.WriteLine("Volume of Box2 : {0}", volume);

        //Add two object as follows:
         Box3 = Box1 + Box2;

        //volume of box 3
         volume = Box3.getVolume();
         Console.WriteLine("Volume of Box3 : {0}", volume);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400

オーバーロード可能および非オーバーロード可能な演算子

次の表では、C#の演算子のオーバーロード機能について説明します-

Sr.No. Operators & Description
1

, -, !, ~, +, --

これらの単項演算子は1つのオペランドを取り、オーバーロードできます。

2

+, -, *,/, %

これらの2項演算子は1つのオペランドを取り、オーバーロードできます。

3

==, !=, <, >, ⇐, >=

比較演算子はオーバーロードできます。

4 *&&,

条件付き論理演算子を直接オーバーロードすることはできません。

5

+=, -=, *=,/=, %=

代入演算子はオーバーロードできません。

6

=, ., ?:, →, new, is, sizeof, typeof

これらの演算子はオーバーロードできません。

上記の議論に照らして、前述の例を拡張し、演算子をもう少しオーバーロードしましょう-

using System;

namespace OperatorOvlApplication {
   class Box {
      private double length;   //Length of a box
      private double breadth;  //Breadth of a box
      private double height;   //Height of a box

      public double getVolume() {
         return length *breadth* height;
      }
      public void setLength( double len ) {
         length = len;
      }
      public void setBreadth( double bre ) {
         breadth = bre;
      }
      public void setHeight( double hei ) {
         height = hei;
      }

     //Overload + operator to add two Box objects.
      public static Box operator+ (Box b, Box c) {
         Box box = new Box();
         box.length = b.length + c.length;
         box.breadth = b.breadth + c.breadth;
         box.height = b.height + c.height;
         return box;
      }
      public static bool operator == (Box lhs, Box rhs) {
         bool status = false;
         if (lhs.length == rhs.length && lhs.height == rhs.height
            && lhs.breadth == rhs.breadth) {

            status = true;
         }
         return status;
      }
      public static bool operator !=(Box lhs, Box rhs) {
         bool status = false;

         if (lhs.length != rhs.length || lhs.height != rhs.height ||
            lhs.breadth != rhs.breadth) {

            status = true;
         }
         return status;
      }
      public static bool operator <(Box lhs, Box rhs) {
         bool status = false;

         if (lhs.length < rhs.length && lhs.height < rhs.height
            && lhs.breadth < rhs.breadth) {

            status = true;
         }
         return status;
      }
      public static bool operator >(Box lhs, Box rhs) {
         bool status = false;

         if (lhs.length > rhs.length && lhs.height >
            rhs.height && lhs.breadth > rhs.breadth) {

            status = true;
         }
         return status;
      }
      public static bool operator <=(Box lhs, Box rhs) {
         bool status = false;

         if (lhs.length <= rhs.length && lhs.height
            <= rhs.height && lhs.breadth <= rhs.breadth) {

            status = true;
         }
         return status;
      }
      public static bool operator >=(Box lhs, Box rhs) {
         bool status = false;

         if (lhs.length >= rhs.length && lhs.height
            >= rhs.height && lhs.breadth >= rhs.breadth) {

            status = true;
         }
         return status;
      }
      public override string ToString() {
         return String.Format("({0}, {1}, {2})", length, breadth, height);
      }
   }
   class Tester {
      static void Main(string[] args) {
         Box Box1 = new Box();  //Declare Box1 of type Box
         Box Box2 = new Box();  //Declare Box2 of type Box
         Box Box3 = new Box();  //Declare Box3 of type Box
         Box Box4 = new Box();
         double volume = 0.0;   //Store the volume of a box here

        //box 1 specification
         Box1.setLength(6.0);
         Box1.setBreadth(7.0);
         Box1.setHeight(5.0);

        //box 2 specification
         Box2.setLength(12.0);
         Box2.setBreadth(13.0);
         Box2.setHeight(10.0);

        //displaying the Boxes using the overloaded ToString():
         Console.WriteLine("Box 1: {0}", Box1.ToString());
         Console.WriteLine("Box 2: {0}", Box2.ToString());

        //volume of box 1
         volume = Box1.getVolume();
         Console.WriteLine("Volume of Box1 : {0}", volume);

        //volume of box 2
         volume = Box2.getVolume();
         Console.WriteLine("Volume of Box2 : {0}", volume);

        //Add two object as follows:
         Box3 = Box1 + Box2;
         Console.WriteLine("Box 3: {0}", Box3.ToString());

        //volume of box 3
         volume = Box3.getVolume();
         Console.WriteLine("Volume of Box3 : {0}", volume);

        //comparing the boxes
         if (Box1 > Box2)
            Console.WriteLine("Box1 is greater than Box2");
         else
            Console.WriteLine("Box1 is not greater than Box2");

         if (Box1 < Box2)
            Console.WriteLine("Box1 is less than Box2");
         else
            Console.WriteLine("Box1 is not less than Box2");

         if (Box1 >= Box2)
            Console.WriteLine("Box1 is greater or equal to Box2");
         else
            Console.WriteLine("Box1 is not greater or equal to Box2");

         if (Box1 <= Box2)
            Console.WriteLine("Box1 is less or equal to Box2");
         else
            Console.WriteLine("Box1 is not less or equal to Box2");

         if (Box1 != Box2)
            Console.WriteLine("Box1 is not equal to Box2");
         else
            Console.WriteLine("Box1 is not greater or equal to Box2");
         Box4 = Box3;

         if (Box3 == Box4)
            Console.WriteLine("Box3 is equal to Box4");
         else
            Console.WriteLine("Box3 is not equal to Box4");

         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Box 1: (6, 7, 5)
Box 2: (12, 13, 10)
Volume of Box1 : 210
Volume of Box2 : 1560
Box 3: (18, 20, 15)
Volume of Box3 : 5400
Box1 is not greater than Box2
Box1 is less than Box2
Box1 is not greater or equal to Box2
Box1 is less or equal to Box2
Box1 is not equal to Box2
Box3 is equal to Box4

C#-インターフェース

インターフェースは、インターフェースを継承するすべてのクラスが従うべき構文上の契約として定義されます。 インターフェイスは、構文コントラクトの 'what' 部分を定義し、派生クラスは、構文コントラクトの 'how' 部分を定義します。

インターフェイスは、インターフェイスのメンバーであるプロパティ、メソッド、およびイベントを定義します。 インターフェイスには、メンバーの宣言のみが含まれます。 メンバーを定義するのは、派生クラスの責任です。 多くの場合、派生クラスが従う標準構造を提供するのに役立ちます。

ある程度まで抽象クラスは同じ目的を果たしますが、基本クラスによって宣言されるメソッドがほとんどなく、派生クラスが機能を実装する場合にほとんど使用されます。

インターフェイスの宣言

インターフェイスは、interfaceキーワードを使用して宣言されます。 クラス宣言に似ています。 インターフェイス文はデフォルトで公開されています。 以下は、インターフェイス宣言の例です-

public interface ITransactions {
  //interface members
   void showTransaction();
   double getAmount();
}

次の例は、上記のインターフェイスの実装を示しています-

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;

namespace InterfaceApplication {

   public interface ITransactions {
     //interface members
      void showTransaction();
      double getAmount();
   }
   public class Transaction : ITransactions {
      private string tCode;
      private string date;
      private double amount;

      public Transaction() {
         tCode = " ";
         date = " ";
         amount = 0.0;
      }
      public Transaction(string c, string d, double a) {
         tCode = c;
         date = d;
         amount = a;
      }
      public double getAmount() {
         return amount;
      }
      public void showTransaction() {
         Console.WriteLine("Transaction: {0}", tCode);
         Console.WriteLine("Date: {0}", date);
         Console.WriteLine("Amount: {0}", getAmount());
      }
   }
   class Tester {

      static void Main(string[] args) {
         Transaction t1 = new Transaction("001", "8/10/2012", 78900.00);
         Transaction t2 = new Transaction("002", "9/10/2012", 451900.00);

         t1.showTransaction();
         t2.showTransaction();
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Transaction: 001
Date: 8/10/2012
Amount: 78900
Transaction: 002
Date: 9/10/2012
Amount: 451900

C#-名前空間

  • 名前空間*は、ある名前のセットを別の名前のセットから分離する方法を提供するために設計されています。 あるネームスペースで宣言されたクラス名は、別のネームスペースで宣言された同じクラス名と競合しません。

名前空間の定義

名前空間の定義は、次のようにキーワード namespace で始まり、その後に名前空間名が続きます-

namespace namespace_name {
  //code declarations
}

関数または変数の名前空間対応バージョンを呼び出すには、次のように名前空間名を追加します-

namespace_name.item_name;

次のプログラムは、名前空間の使用を示しています-

using System;

namespace first_space {
   class namespace_cl {
      public void func() {
         Console.WriteLine("Inside first_space");
      }
   }
}
namespace second_space {
   class namespace_cl {
      public void func() {
         Console.WriteLine("Inside second_space");
      }
   }
}
class TestClass {
   static void Main(string[] args) {
      first_space.namespace_cl fc = new first_space.namespace_cl();
      second_space.namespace_cl sc = new second_space.namespace_cl();
      fc.func();
      sc.func();
      Console.ReadKey();
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Inside first_space
Inside second_space

_using_キーワード

*using* キーワードは、プログラムが指定された名前空間の名前を使用していることを示します。 たとえば、プログラムで *System* 名前空間を使用しています。 クラスConsoleはそこで定義されています。 私たちはただ書く-
Console.WriteLine ("Hello there");

完全修飾名を次のように書くこともできます-

System.Console.WriteLine("Hello there");
*using* 名前空間ディレクティブを使用して、名前空間の先頭に追加することも回避できます。 このディレクティブは、後続のコードが指定された名前空間の名前を使用していることをコンパイラーに伝えます。 したがって、名前空間は、次のコードのために暗示されています-

ディレクティブを使用して、前述の例を書き換えましょう-

using System;
using first_space;
using second_space;

namespace first_space {
   class abc {
      public void func() {
         Console.WriteLine("Inside first_space");
      }
   }
}
namespace second_space {
   class efg {
      public void func() {
         Console.WriteLine("Inside second_space");
      }
   }
}
class TestClass {
   static void Main(string[] args) {
      abc fc = new abc();
      efg sc = new efg();
      fc.func();
      sc.func();
      Console.ReadKey();
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Inside first_space
Inside second_space

入れ子になった名前空間

次のように、別のネームスペース内にあるネームスペースを定義できます-

namespace namespace_name1 {

  //code declarations
   namespace namespace_name2 {
     //code declarations
   }
}

次のようにドット(。)演算子を使用して、ネストされた名前空間のメンバーにアクセスできます-

using System;
using first_space;
using first_space.second_space;

namespace first_space {
   class abc {
      public void func() {
         Console.WriteLine("Inside first_space");
      }
   }
   namespace second_space {
      class efg {
         public void func() {
            Console.WriteLine("Inside second_space");
         }
      }
   }
}
class TestClass {
   static void Main(string[] args) {
      abc fc = new abc();
      efg sc = new efg();
      fc.func();
      sc.func();
      Console.ReadKey();
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Inside first_space
Inside second_space

C#-プリプロセッサディレクティブ

プリプロセッサディレクティブは、実際のコンパイルを開始する前に情報を前処理するようにコンパイラに指示します。

すべてのプリプロセッサディレクティブは#で始まり、行のプリプロセッサディレクティブの前には空白文字のみが表示されます。 プリプロセッサディレクティブはステートメントではないため、セミコロン(;)で終了しません。

C#コンパイラには個別のプリプロセッサがありません。ただし、ディレクティブは存在するかのように処理されます。 C#では、プリプロセッサディレクティブを使用して条件付きコンパイルを支援します。 CおよびC ++ディレクティブとは異なり、マクロの作成には使用されません。 プリプロセッサディレクティブは、行の唯一の命令でなければなりません。

C#のプリプロセッサディレクティブ

次の表に、C#で使用可能なプリプロセッサディレクティブを示します-

Sr.No. Preprocessor Directive & Description
1

#define

シンボルと呼ばれる一連の文字を定義します。

2

#undef

シンボルの定義を解除できます。

3

#if

これにより、1つまたは複数のシンボルをテストして、trueと評価されるかどうかを確認できます。

4

#else

  1. ifとともに複合条件ディレクティブを作成できます。
5

#elif

複合条件付きディレクティブを作成できます。

6

#endif

条件付きディレクティブの終わりを指定します。

7

#line

これにより、コンパイラの行番号と(オプションで)エラーおよび警告のファイル名出力を変更できます。

8

#error

コード内の特定の場所からエラーを生成できます。

9

#warning

コードの特定の場所からレベル1の警告を生成できます。

10

#region

Visual Studioコードエディターのアウトライン機能を使用するときに展開または縮小できるコードブロックを指定できます。

11

#endregion

  1. regionブロックの終わりを示します。

#defineプリプロセッサ

  1. defineプリプロセッサディレクティブは、シンボリック定数を作成します。
  1. defineを使用すると、シンボルを#ifディレクティブに渡される式として使用することにより、式がtrueと評価されるようにシンボルを定義できます。 その構文は次のとおりです-
#define symbol

次のプログラムはこれを示しています-

#define PI
using System;

namespace PreprocessorDAppl {
   class Program {
      static void Main(string[] args) {
         #if (PI)
            Console.WriteLine("PI is defined");
         #else
            Console.WriteLine("PI is not defined");
         #endif
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

PI is defined

条件付きディレクティブ

  1. ifディレクティブを使用して、条件ディレクティブを作成できます。 条件ディレクティブは、1つまたは複数のシンボルをテストして、それらがtrueと評価されるかどうかを確認するのに役立ちます。 真と評価される場合、コンパイラは#ifと次のディレクティブの間のすべてのコードを評価します。

条件付きディレクティブの構文は-

#if symbol [operator symbol]...

ここで、_symbol_はテストするシンボルの名前です。 trueとfalseを使用したり、否定演算子を使用してシンボルを追加することもできます。

_operator symbol_は、シンボルの評価に使用される演算子です。 演算子は次のいずれかになります-

  • ==(平等)
  • !=(不等式)
  • &&(および) *|| (または)

括弧でシンボルと演算子をグループ化することもできます。 条件付きディレクティブは、デバッグビルド用のコードのコンパイルまたは特定の構成用のコンパイルに使用されます。* #if ディレクティブで始まる条件付きディレクティブは、#endif *ディレクティブで明示的に終了する必要があります。

次のプログラムは、条件付きディレクティブの使用を示しています-

#define DEBUG
#define VC_V10
using System;

public class TestClass {
   public static void Main() {
      #if (DEBUG && !VC_V10)
         Console.WriteLine("DEBUG is defined");
      #elif (!DEBUG && VC_V10)
         Console.WriteLine("VC_V10 is defined");
      #elif (DEBUG && VC_V10)
         Console.WriteLine("DEBUG and VC_V10 are defined");
      #else
         Console.WriteLine("DEBUG and VC_V10 are not defined");
      #endif
      Console.ReadKey();
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

DEBUG and VC_V10 are defined

C#-正規表現

  • 正規表現*は、入力テキストと照合できるパターンです。 .Netフレームワークは、このようなマッチングを可能にする正規表現エンジンを提供します。 パターンは、1つ以上の文字リテラル、演算子、または構造で構成されます。

正規表現を定義するための構成

正規表現を定義できる文字、演算子、および構造のさまざまなカテゴリがあります。 次のリンクをクリックして、これらの構造を見つけます。

  • リンク:/csharp/csharp_character_escapes [文字エスケープ]
  • リンク:/csharp/csharp_character_classes [文字クラス]
  • リンク:/csharp/csharp_anchors [アンカー]
  • リンク:/csharp/csharp_grouping_constructs [グループ化構成]
  • リンク:/csharp/csharp_quantifiers [Quantifiers]
  • リンク:/csharp/csharp_backreference_constructs [バックリファレンスコンストラクト]
  • リンク:/csharp/csharp_alternation_constructs [代替構成]
  • リンク:/csharp/csharp_substitutions [Substitutions] *リンク:/csharp/csharp_miscellaneous_constructs [その他の構成]

正規表現クラス

Regexクラスは、正規表現を表すために使用されます。 以下の一般的に使用される方法があります-

Sr.No. Methods & Description
1
  • public bool IsMatch(string input)*

Regexコンストラクターで指定された正規表現が、指定された入力文字列で一致を見つけるかどうかを示します。

2

public bool IsMatch(string input, int startat)

Regexコンストラクターで指定された正規表現が、文字列の指定された開始位置から始まる、指定された入力文字列で一致を見つけるかどうかを示します。

3

public static bool IsMatch(string input, string pattern)

指定された正規表現が指定された入力文字列で一致を見つけるかどうかを示します。

4

public MatchCollection Matches(string input)

正規表現のすべての出現について、指定された入力文字列を検索します。

5

public string Replace(string input, string replacement)

指定された入力文字列で、正規表現パターンに一致するすべての文字列を指定された置換文字列に置き換えます。

6

public string[] Split(string input)

Regexコンストラクターで指定された正規表現パターンで定義された位置で、入力文字列を部分文字列の配列に分割します。

メソッドとプロパティの完全なリストについては、C#のMicrosoftドキュメントをお読みください。

例1

次の例では、「S」で始まる単語に一致します-

using System;
using System.Text.RegularExpressions;

namespace RegExApplication {
   class Program {
      private static void showMatch(string text, string expr) {
         Console.WriteLine("The Expression: " + expr);
         MatchCollection mc = Regex.Matches(text, expr);

         foreach (Match m in mc) {
            Console.WriteLine(m);
         }
      }
      static void Main(string[] args) {
         string str = "A Thousand Splendid Suns";

         Console.WriteLine("Matching words that start with 'S': ");
         showMatch(str, @"\bS\S*");
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Matching words that start with 'S':
The Expression: \bS\S*
Splendid
Suns

例2

次の例では、「m」で始まり「e」で終わる単語に一致します-

using System;
using System.Text.RegularExpressions;

namespace RegExApplication {
   class Program {
      private static void showMatch(string text, string expr) {
         Console.WriteLine("The Expression: " + expr);
         MatchCollection mc = Regex.Matches(text, expr);

         foreach (Match m in mc) {
            Console.WriteLine(m);
         }
      }
      static void Main(string[] args) {
         string str = "make maze and manage to measure it";

         Console.WriteLine("Matching words start with 'm' and ends with 'e':");
         showMatch(str, @"\bm\S*e\b");
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Matching words start with 'm' and ends with 'e':
The Expression: \bm\S*e\b
make
maze
manage
measure

実施例3

この例では、余分な空白を置き換えます-

using System;
using System.Text.RegularExpressions;

namespace RegExApplication {
   class Program {
      static void Main(string[] args) {
         string input = "Hello   World   ";
         string pattern = "\\s+";
         string replacement = " ";

         Regex rgx = new Regex(pattern);
         string result = rgx.Replace(input, replacement);

         Console.WriteLine("Original String: {0}", input);
         Console.WriteLine("Replacement String: {0}", result);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Original String: Hello World
Replacement String: Hello World

C#-例外処理

例外は、プログラムの実行中に発生する問題です。 C#例外は、ゼロ除算の試行など、プログラムの実行中に発生する例外的な状況への応答です。

例外は、プログラムのある部分から別の部分に制御を移す方法を提供します。 C#例外処理は、 trycatchfinally 、および throw の4つのキーワードに基づいて構築されています。

  • try -tryブロックは、特定の例外がアクティブになるコードのブロックを識別します。 その後に1つ以上のcatchブロックが続きます。
  • catch -プログラムは、問題を処理するプログラム内の場所で例外ハンドラーを使用して例外をキャッチします。 catchキーワードは、例外のキャッチを示します。
  • finally -finallyブロックは、例外がスローされるかどうかに関係なく、指定された一連のステートメントを実行するために使用されます。 たとえば、ファイルを開く場合は、例外が発生したかどうかにかかわらず、ファイルを閉じる必要があります。
  • throw -問題が発生すると、プログラムは例外をスローします。 これは、throwキーワードを使用して行われます。

構文

ブロックが例外を発生させると仮定すると、メソッドはtryキーワードとcatchキーワードの組み合わせを使用して例外をキャッチします。 try/catchブロックは、例外を生成する可能性のあるコードの周りに配置されます。 try/catchブロック内のコードは保護されたコードと呼ばれ、try/catchを使用するための構文は次のようになります-

try {
  //statements causing exception
} catch( ExceptionName e1 ) {
  //error handling code
} catch( ExceptionName e2 ) {
  //error handling code
} catch( ExceptionName eN ) {
  //error handling code
} finally {
  //statements to be executed
}

tryブロックが異なる状況で複数の例外を発生させた場合に備えて、複数のcatchステートメントをリストダウンして、異なるタイプの例外をキャッチできます。

C#の例外クラス

C#例外はクラスによって表されます。 C#の例外クラスは、主に System.Exception クラスから直接または間接的に派生します。 System.Exceptionクラスから派生した例外クラスには、 System.ApplicationException および System.SystemException クラスがあります。

*System.ApplicationException* クラスは、アプリケーションプログラムによって生成された例外をサポートします。 したがって、プログラマーによって定義された例外は、このクラスから派生する必要があります。
*System.SystemException* クラスは、事前定義されたすべてのシステム例外の基本クラスです。

次の表は、Sytem.SystemExceptionクラスから派生した定義済みの例外クラスの一部を示しています-

Sr.No. Exception Class & Description
1

System.IO.IOException

I/Oエラーを処理します。

2

System.IndexOutOfRangeException

メソッドが範囲外の配列インデックスを参照するときに生成されるエラーを処理します。

3

System.ArrayTypeMismatchException

タイプが配列タイプと一致しない場合に生成されるエラーを処理します。

4

System.NullReferenceException

nullオブジェクトの参照から生成されたエラーを処理します。

5

System.DivideByZeroException

配当をゼロで除算することで生成されるエラーを処理します。

6

System.InvalidCastException

型キャスト中に生成されたエラーを処理します。

7

System.OutOfMemoryException

空きメモリ不足から生成されたエラーを処理します。

8

System.StackOverflowException

スタックオーバーフローから生成されたエラーを処理します。

例外処理

C#は、tryブロックとcatchブロックの形式で例外処理の構造化されたソリューションを提供します。 これらのブロックを使用すると、コアプログラムステートメントがエラー処理ステートメントから分離されます。

これらのエラー処理ブロックは、 trycatch 、および finally キーワードを使用して実装されます。 以下は、ゼロ条件による除算が発生したときに例外をスローする例です-

using System;

namespace ErrorHandlingApplication {
   class DivNumbers {
      int result;

      DivNumbers() {
         result = 0;
      }
      public void division(int num1, int num2) {
         try {
            result = num1/num2;
         } catch (DivideByZeroException e) {
            Console.WriteLine("Exception caught: {0}", e);
         } finally {
            Console.WriteLine("Result: {0}", result);
         }
      }
      static void Main(string[] args) {
         DivNumbers d = new DivNumbers();
         d.division(25, 0);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Exception caught: System.DivideByZeroException: Attempted to divide by zero.
at ...
Result: 0

ユーザー定義の例外の作成

独自の例外を定義することもできます。 ユーザー定義の例外クラスは、 Exception クラスから派生しています。 次の例はこれを示しています-

using System;

namespace UserDefinedException {
   class TestTemperature {
      static void Main(string[] args) {
         Temperature temp = new Temperature();
         try {
            temp.showTemp();
         } catch(TempIsZeroException e) {
            Console.WriteLine("TempIsZeroException: {0}", e.Message);
         }
         Console.ReadKey();
      }
   }
}
public class TempIsZeroException: Exception {
   public TempIsZeroException(string message): base(message) {
   }
}
public class Temperature {
   int temperature = 0;

   public void showTemp() {

      if(temperature == 0) {
         throw (new TempIsZeroException("Zero Temperature found"));
      } else {
         Console.WriteLine("Temperature: {0}", temperature);
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

TempIsZeroException: Zero Temperature found

オブジェクトを投げる

*System.Exception* クラスから直接または間接的に派生したオブジェクトの場合、オブジェクトをスローできます。 あなたは、現在のオブジェクトをスローするようにキャッチブロックでスローステートメントを使用することができます-
Catch(Exception e) {
   ...
   Throw e
}

C#-ファイルI/O

  • ファイル*は、特定の名前とディレクトリパスでディスクに保存されたデータのコレクションです。 ファイルが読み取りまたは書き込みのために開かれると、*ストリーム*になります。

ストリームは、基本的に通信パスを通過する一連のバイトです。 2つのメインストリームがあります:入力ストリーム*および*出力ストリーム。 *入力ストリーム*は、ファイルからのデータの読み取り(読み取り操作)に使用され、*出力ストリーム*はファイルへの書き込み(書き込み操作)に使用されます。

C#I/Oクラス

System.IO名前空間には、ファイルの作成と削除、ファイルの読み取りまたは書き込み、ファイルのクローズなど、ファイルを使用した多数の操作を実行するために使用されるさまざまなクラスがあります。

次の表は、System.IO名前空間で一般的に使用されるいくつかの非抽象クラスを示しています-

Sr.No. I/O Class & Description
1

BinaryReader

バイナリストリームからプリミティブデータを読み取ります。

2

BinaryWriter

プリミティブ形式のデータをバイナリ形式で書き込みます。

3

BufferedStream

バイトストリームの一時ストレージ。

4

Directory

ディレクトリ構造の操作を支援します。

5

DirectoryInfo

ディレクトリで操作を実行するために使用されます。

6

DriveInfo

ドライブに関する情報を提供します。

7

File

ファイルの操作に役立ちます。

8

FileInfo

ファイルの操作を実行するために使用されます。

9

FileStream

ファイル内の任意の場所から読み書きするために使用されます。

10

MemoryStream

メモリに保存されたストリーミングデータへのランダムアクセスに使用されます。

11

Path

パス情報に対して操作を実行します。

12

StreamReader

バイトストリームから文字を読み取るために使用されます。

13

StreamWriter

文字をストリームに書き込むために使用されます。

14

StringReader

文字列バッファーからの読み取りに使用されます。

15

StringWriter

文字列バッファへの書き込みに使用されます。

FileStreamクラス

System.IO名前空間の FileStream クラスは、ファイルの読み取り、書き込み、およびファイルのクローズに役立ちます。 このクラスは、抽象クラスStreamから派生しています。

*FileStream* オブジェクトを作成して、新しいファイルを作成するか、既存のファイルを開く必要があります。 *FileStream* オブジェクトを作成するための構文は次のとおりです-
FileStream <object_name> = new FileStream( <file_name>, <FileMode Enumerator>,
   <FileAccess Enumerator>, <FileShare Enumerator>);

たとえば、次のように* sample.txtという名前のファイルを読み取るためにFileStreamオブジェクト F を作成します-

FileStream F = new FileStream("sample.txt", FileMode.Open, FileAccess.Read,
   FileShare.Read);
Sr.No. Parameter & Description
1

FileMode

  • FileMode* 列挙子は、ファイルを開くためのさまざまなメソッドを定義します。 FileMode列挙子のメンバーは-
  • 追加-既存のファイルを開き、ファイルの最後にカーソルを置くか、ファイルが存在しない場合はファイルを作成します。
  • 作成-新しいファイルを作成します。
  • CreateNew -オペレーティングシステムに新しいファイルを作成するように指定します。
  • 開く-既存のファイルを開きます。
  • OpenOrCreate -ファイルが存在する場合はそれを開く必要があることをオペレーティングシステムに指定し、そうでない場合は新しいファイルを作成する必要があります。
  • 切り捨て-既存のファイルを開き、そのサイズをゼロバイトに切り捨てます。
2

FileAccess

  • FileAccess* 列挙子には、 *Read* 、 *ReadWrite* 、および *Write* のメンバーがあります。
3

FileShare

  • FileShare* 列挙子には、次のメンバーがあります-
  • Inheritable -ファイルハンドルが子プロセスに継承を渡すことができる
  • なし-現在のファイルの共有を拒否します
  • 読み取り-読み取り用にファイルを開くことができます。
  • ReadWrite -読み取りおよび書き込み用にファイルを開くことができます
  • 書き込み-書き込み用にファイルを開くことができます

次のプログラムは、 FileStream クラスの使用方法を示しています-

using System;
using System.IO;

namespace FileIOApplication {
   class Program {
      static void Main(string[] args) {
         FileStream F = new FileStream("test.dat", FileMode.OpenOrCreate,
            FileAccess.ReadWrite);

         for (int i = 1; i <= 20; i++) {
            F.WriteByte((byte)i);
         }
         F.Position = 0;
         for (int i = 0; i <= 20; i++) {
            Console.Write(F.ReadByte() + " ");
         }
         F.Close();
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 -1

C#の高度なファイル操作

前の例では、C#での単純なファイル操作を提供しています。 ただし、C#System.IOクラスの非常に強力な機能を利用するには、これらのクラスの一般的に使用されるプロパティとメソッドを知る必要があります。

Sr.No. Topic & Description
1

Reading from and Writing into Text files

テキストファイルの読み取りと書き込みが含まれます。 StreamReader および StreamWriter クラスはそれを達成するのに役立ちます。

2

Reading from and Writing into Binary files

これには、バイナリファイルの読み取りと書き込みが含まれます。 BinaryReader および BinaryWriter クラスは、これを達成するのに役立ちます。

3

Manipulating the Windows file system

これにより、C#プログラマーはWindowsファイルとディレクトリを参照および検索できます。

C#-属性

*attribute* は、クラス、メソッド、構造体、列挙子、アセンブリなどのさまざまな要素の動作に関する情報をランタイムに伝えるために使用される宣言タグです。 あなたのプログラムで。 属性を使用して、宣言情報をプログラムに追加できます。 宣言タグは、使用される要素の上に配置された角括弧([])で表されます。

属性は、コンパイラ命令などのメタデータや、コメント、説明、メソッド、クラスなどの他の情報をプログラムに追加するために使用されます。 .Net Frameworkは、2つのタイプの属性を提供します:事前定義された属性と_custom built_属性。

属性を指定する

属性を指定するための構文は次のとおりです-

[attribute(positional_parameters, name_parameter = value, ...)]
element

属性の名前とその値は、属性が適用される要素の前に、角括弧内で指定されます。 位置パラメータは必須情報を指定し、名前パラメータはオプション情報を指定します。

事前定義された属性

  • AttributeUsage
  • 条件付き
  • 廃止された

AttributeUsage

事前定義された属性 AttributeUsage は、カスタム属性クラスの使用方法を説明しています。 属性を適用できるアイテムのタイプを指定します。

この属性を指定するための構文は次のとおりです-

[AttributeUsage (
   validon,
   AllowMultiple = allowmultiple,
   Inherited = inherited
)]

どこで、

  • パラメーターvalidonは、属性を配置できる言語要素を指定します。 列挙子_AttributeTargets_の値の組み合わせです。 デフォルト値は_AttributeTargets.All_です。
  • パラメーター_allowmultiple_(オプション)は、この属性の_AllowMultiple_プロパティーの値(ブール値)を提供します。 これが当てはまる場合、属性は多目的です。 デフォルトはfalse(使い捨て)です。
  • 継承されたパラメーター(オプション)は、この属性の_Inherited_プロパティの値、ブール値を提供します。 trueの場合、属性は派生クラスに継承されます。 デフォルト値はfalseです(継承されません)。

例えば、

[AttributeUsage(
   AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)]

条件付き

この事前定義された属性は、実行が指定された前処理識別子に依存する条件付きメソッドをマークします。

*Debug* や *Trace* などの指定値に応じて、メソッド呼び出しの条件付きコンパイルが発生します。 たとえば、コードのデバッグ中に変数の値を表示します。

この属性を指定するための構文は次のとおりです-

[Conditional(
   conditionalSymbol
)]

例えば、

[Conditional("DEBUG")]

次の例は、属性を示しています-

#define DEBUG
using System;
using System.Diagnostics;

public class Myclass {
   [Conditional("DEBUG")]

   public static void Message(string msg) {
      Console.WriteLine(msg);
   }
}
class Test {
   static void function1() {
      Myclass.Message("In Function 1.");
      function2();
   }
   static void function2() {
      Myclass.Message("In Function 2.");
   }
   public static void Main() {
      Myclass.Message("In Main function.");
      function1();
      Console.ReadKey();
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

In Main function
In Function 1
In Function 2

廃止された

この事前定義された属性は、使用すべきでないプログラムエンティティをマークします。 特定のターゲット要素を破棄するようコンパイラーに通知できます。 たとえば、新しいメソッドがクラスで使用されており、クラスで古いメソッドを保持したい場合、古いメソッドの代わりに新しいメソッドを使用する必要があるというメッセージを表示することにより、古いメソッドとしてマークすることができます。

この属性を指定するための構文は次のとおりです-

[Obsolete (
   message
)]

[Obsolete (
   message,
   iserror
)]

どこで、

  • パラメータ_message_は、アイテムが廃止された理由と代わりに使用するものを説明する文字列です。
  • パラメーター_iserror_はブール値です。 値がtrueの場合、コンパイラはアイテムの使用をエラーとして扱う必要があります。 デフォルト値はfalseです(コンパイラーは警告を生成します)。

次のプログラムはこれを示しています-

using System;

public class MyClass {
   [Obsolete("Don't use OldMethod, use NewMethod instead", true)]

   static void OldMethod() {
      Console.WriteLine("It is the old method");
   }
   static void NewMethod() {
      Console.WriteLine("It is the new method");
   }
   public static void Main() {
      OldMethod();
   }
}

あなたがプログラムをコンパイルしようとすると、コンパイラは次のようなエラーメッセージを出します-

 Don't use OldMethod, use NewMethod instead

カスタム属性の作成

Net Frameworkを使用すると、宣言型の情報を保存したり、実行時に取得したりできるカスタム属性を作成できます。 この情報は、設計基準とアプリケーションのニーズに応じて、任意のターゲット要素に関連付けることができます。.

カスタム属性の作成と使用には、4つのステップが含まれます-

  • カスタム属性の宣言
  • カスタム属性の構築
  • ターゲットプログラム要素にカスタム属性を適用する
  • リフレクションを介して属性にアクセスする

最後のステップでは、簡単なプログラムを作成してメタデータを読み、さまざまな表記法を見つけます。 メタデータは、データに関するデータまたは他のデータの説明に使用される情報です。 このプログラムは、実行時に属性にアクセスするためにリフレクションを使用する必要があります。 これについては、次の章で説明します。

カスタム属性の宣言

新しいカスタム属性は、 System.Attribute クラスから派生する必要があります。 例えば、

//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(
   AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)]

public class DeBugInfo : System.Attribute

上記のコードでは、_DeBugInfo_という名前のカスタム属性を宣言しています。

カスタム属性の構築

_DeBugInfo_という名前のカスタム属性を作成します。この属性には、プログラムのデバッグによって取得された情報が格納されます。 それは次の情報を保存しましょう-

  • バグのコード番号
  • バグを特定した開発者の名前
  • コードの最後のレビューの日付 *開発者のコ​​メントを保存するための文字列メッセージ

_DeBugInfo_クラスには、最初の3つの情報を保存するための3つのプライベートプロパティと、メッセージを保存するためのパブリックプロパティがあります。 したがって、バグ番号、開発者の名前、およびレビューの日付はDeBugInfoクラスの定位置パラメーターであり、メッセージはオプションのパラメーターまたは名前付きパラメーターです。

各属性には少なくとも1つのコンストラクターが必要です。 位置パラメーターは、コンストラクターを介して渡す必要があります。 次のコードは_DeBugInfo_クラスを示しています-

//a custom attribute BugFix to be assigned to a class and its members
[AttributeUsage(
   AttributeTargets.Class |
   AttributeTargets.Constructor |
   AttributeTargets.Field |
   AttributeTargets.Method |
   AttributeTargets.Property,
   AllowMultiple = true)]

public class DeBugInfo : System.Attribute {
   private int bugNo;
   private string developer;
   private string lastReview;
   public string message;

   public DeBugInfo(int bg, string dev, string d) {
      this.bugNo = bg;
      this.developer = dev;
      this.lastReview = d;
   }
   public int BugNo {
      get {
         return bugNo;
      }
   }
   public string Developer {
      get {
         return developer;
      }
   }
   public string LastReview {
      get {
         return lastReview;
      }
   }
   public string Message {
      get {
         return message;
      }
      set {
         message = value;
      }
   }
}

カスタム属性の適用

属性は、そのターゲットの直前に配置することにより適用されます-

[DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
[DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]
class Rectangle {
  //member variables
   protected double length;
   protected double width;
   public Rectangle(double l, double w) {
      length = l;
      width = w;
   }
   [DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]

   public double GetArea() {
      return length* width;
   }
   [DeBugInfo(56, "Zara Ali", "19/10/2012")]

   public void Display() {
      Console.WriteLine("Length: {0}", length);
      Console.WriteLine("Width: {0}", width);
      Console.WriteLine("Area: {0}", GetArea());
   }
}

次の章では、Reflectionクラスオブジェクトを使用して属性情報を取得します。

C#-リフレクション

*Reflection* オブジェクトは、実行時に型情報を取得するために使用されます。 実行中のプログラムのメタデータへのアクセスを提供するクラスは、 *System.Reflection* 名前空間にあります。
*System.Reflection* 名前空間には、アプリケーションに関する情報を取得し、アプリケーションに型、値、およびオブジェクトを動的に追加できるクラスが含まれています。

反射の応用

Reflectionには次のアプリケーションがあります-

  • 実行時に属性情報を表示できます。
  • アセンブリ内のさまざまな型を調べて、これらの型をインスタンス化できます。
  • メソッドとプロパティへの遅延バインディングを許可します
  • 実行時に新しいタイプを作成し、それらのタイプを使用していくつかのタスクを実行できます。

メタデータの表示

前の章で、リフレクションを使用して属性情報を表示できることを説明しました。

*System.Reflection* クラスの *MemberInfo* オブジェクトは、クラスに関連付けられた属性を検出するために初期化する必要があります。 これを行うには、次のように、ターゲットクラスのオブジェクトを定義します-
System.Reflection.MemberInfo info = typeof(MyClass);

次のプログラムはこれを示しています-

using System;

[AttributeUsage(AttributeTargets.All)]
public class HelpAttribute : System.Attribute {
   public readonly string Url;

   public string Topic  //Topic is a named parameter {
      get {
         return topic;
      }
      set {
         topic = value;
      }
   }
   public HelpAttribute(string url)  //url is a positional parameter {
      this.Url = url;
   }
   private string topic;
}

[HelpAttribute("Information on the class MyClass")]
class MyClass {

}

namespace AttributeAppl {
   class Program {
      static void Main(string[] args) {
         System.Reflection.MemberInfo info = typeof(MyClass);
         object[] attributes = info.GetCustomAttributes(true);

         for (int i = 0; i < attributes.Length; i++) {
            System.Console.WriteLine(attributes[i]);
         }
         Console.ReadKey();
      }
   }
}

コンパイルして実行すると、クラス_MyClass_に付加されたカスタム属性の名前が表示されます-

HelpAttribute

この例では、前の章で作成した_DeBugInfo_属性を使用し、リフレクションを使用して_Rectangle_クラスのメタデータを読み取ります。

using System;
using System.Reflection;

namespace BugFixApplication {
  //a custom attribute BugFix to be assigned to a class and its members
   [AttributeUsage(
      AttributeTargets.Class |
      AttributeTargets.Constructor |
      AttributeTargets.Field |
      AttributeTargets.Method |
      AttributeTargets.Property,
      AllowMultiple = true)]

   public class DeBugInfo : System.Attribute {
      private int bugNo;
      private string developer;
      private string lastReview;
      public string message;

      public DeBugInfo(int bg, string dev, string d) {
         this.bugNo = bg;
         this.developer = dev;
         this.lastReview = d;
      }
      public int BugNo {
         get {
            return bugNo;
         }
      }
      public string Developer {
         get {
            return developer;
         }
      }
      public string LastReview {
         get {
            return lastReview;
         }
      }
      public string Message {
         get {
            return message;
         }
         set {
            message = value;
         }
      }
   }
   [DeBugInfo(45, "Zara Ali", "12/8/2012", Message = "Return type mismatch")]
   [DeBugInfo(49, "Nuha Ali", "10/10/2012", Message = "Unused variable")]

   class Rectangle {
     //member variables
      protected double length;
      protected double width;

      public Rectangle(double l, double w) {
         length = l;
         width = w;
      }
      [DeBugInfo(55, "Zara Ali", "19/10/2012", Message = "Return type mismatch")]
      public double GetArea() {
         return length * width;
      }
      [DeBugInfo(56, "Zara Ali", "19/10/2012")]
      public void Display() {
         Console.WriteLine("Length: {0}", length);
         Console.WriteLine("Width: {0}", width);
         Console.WriteLine("Area: {0}", GetArea());
      }
   }//end class Rectangle

   class ExecuteRectangle {
      static void Main(string[] args) {
         Rectangle r = new Rectangle(4.5, 7.5);
         r.Display();
         Type type = typeof(Rectangle);

        //iterating through the attribtues of the Rectangle class
         foreach (Object attributes in type.GetCustomAttributes(false)) {
            DeBugInfo dbi = (DeBugInfo)attributes;

            if (null != dbi) {
               Console.WriteLine("Bug no: {0}", dbi.BugNo);
               Console.WriteLine("Developer: {0}", dbi.Developer);
               Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
               Console.WriteLine("Remarks: {0}", dbi.Message);
            }
         }

        //iterating through the method attribtues
         foreach (MethodInfo m in type.GetMethods()) {

            foreach (Attribute a in m.GetCustomAttributes(true)) {
               DeBugInfo dbi = (DeBugInfo)a;

               if (null != dbi) {
                  Console.WriteLine("Bug no: {0}, for Method: {1}", dbi.BugNo, m.Name);
                  Console.WriteLine("Developer: {0}", dbi.Developer);
                  Console.WriteLine("Last Reviewed: {0}", dbi.LastReview);
                  Console.WriteLine("Remarks: {0}", dbi.Message);
               }
            }
         }
         Console.ReadLine();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Length: 4.5
Width: 7.5
Area: 33.75
Bug No: 49
Developer: Nuha Ali
Last Reviewed: 10/10/2012
Remarks: Unused variable
Bug No: 45
Developer: Zara Ali
Last Reviewed: 12/8/2012
Remarks: Return type mismatch
Bug No: 55, for Method: GetArea
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks: Return type mismatch
Bug No: 56, for Method: Display
Developer: Zara Ali
Last Reviewed: 19/10/2012
Remarks:

C#-プロパティ

プロパティ*は、クラス、構造、およびインターフェイスの名前付きメンバーです。 クラスまたは構造内のメンバー変数またはメソッドは、*フィールド*と呼ばれます。 プロパティはフィールドの拡張であり、同じ構文を使用してアクセスされます。 これらは *accessors を使用し、これを介してプライベートフィールドの値を読み取り、書き込み、または操作できます。

プロパティは格納場所を指定しません。 代わりに、値を読み取り、書き込み、または計算する accessors があります。

たとえば、年齢、名前、コードのプライベートフィールドを持つStudentという名前のクラスがあるとします。 クラススコープ外からこれらのフィールドに直接アクセスすることはできませんが、これらのプライベートフィールドにアクセスするためのプロパティを持つことはできます。

アクセサ

プロパティの accessor には、プロパティの取得(読み取りまたは計算)または設定(書き込み)に役立つ実行可能ステートメントが含まれています。 アクセサー宣言には、getアクセサー、setアクセサー、またはその両方を含めることができます。 たとえば-

//Declare a Code property of type string:
public string Code {
   get {
      return code;
   }
   set {
      code = value;
   }
}

//Declare a Name property of type string:
public string Name {
   get {
      return name;
   }
   set {
      name = value;
   }
}

//Declare a Age property of type int:
public int Age {
   get {
      return age;
   }
   set {
      age = value;
   }
}

次の例は、プロパティの使用を示しています-

using System;
namespace finddevguides {
   class Student {
      private string code = "N.A";
      private string name = "not known";
      private int age = 0;

     //Declare a Code property of type string:
      public string Code {
         get {
            return code;
         }
         set {
            code = value;
         }
      }

     //Declare a Name property of type string:
      public string Name {
         get {
            return name;
         }
         set {
            name = value;
         }
      }

     //Declare a Age property of type int:
      public int Age {
         get {
            return age;
         }
         set {
            age = value;
         }
      }
      public override string ToString() {
         return "Code = " + Code +", Name = " + Name + ", Age = " + Age;
      }
   }

   class ExampleDemo {
      public static void Main() {

        //Create a new Student object:
         Student s = new Student();

        //Setting code, name and the age of the student
         s.Code = "001";
         s.Name = "Zara";
         s.Age = 9;
         Console.WriteLine("Student Info: {0}", s);

        //let us increase age
         s.Age += 1;
         Console.WriteLine("Student Info: {0}", s);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Student Info: Code = 001, Name = Zara, Age = 9
Student Info: Code = 001, Name = Zara, Age = 10

抽象プロパティ

抽象クラスには、派生クラスに実装する必要のある抽象プロパティを含めることができます。 次のプログラムはこれを示しています-

using System;

namespace finddevguides {
   public abstract class Person {
      public abstract string Name {
         get;
         set;
      }
      public abstract int Age {
         get;
         set;
      }
   }
   class Student : Person {
      private string code = "N.A";
      private string name = "N.A";
      private int age = 0;

     //Declare a Code property of type string:
      public string Code {
         get {
            return code;
         }
         set {
            code = value;
         }
      }

     //Declare a Name property of type string:
      public override string Name {
         get {
            return name;
         }
         set {
            name = value;
         }
      }

     //Declare a Age property of type int:
      public override int Age {
         get {
            return age;
         }
         set {
            age = value;
         }
      }
      public override string ToString() {
         return "Code = " + Code +", Name = " + Name + ", Age = " + Age;
      }
   }

   class ExampleDemo {
      public static void Main() {
        //Create a new Student object:
         Student s = new Student();

        //Setting code, name and the age of the student
         s.Code = "001";
         s.Name = "Zara";
         s.Age = 9;
         Console.WriteLine("Student Info:- {0}", s);

        //let us increase age
         s.Age += 1;
         Console.WriteLine("Student Info:- {0}", s);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Student Info: Code = 001, Name = Zara, Age = 9
Student Info: Code = 001, Name = Zara, Age = 10

C#-インデクサー

*indexer* を使用すると、配列などのオブジェクトにインデックスを付けることができます。 クラスのインデクサーを定義すると、このクラスは*仮想配列*と同様に動作します。 その後、配列アクセス演算子([])を使用してこのクラスのインスタンスにアクセスできます。

構文

一次元のインデクサーには、次の構文があります-

element-type this[int index] {

  //The get accessor.
   get {
     //return the value specified by index
   }

  //The set accessor.
   set {
     //set the value specified by index
   }
}

インデクサーの使用

インデクサーの動作の宣言は、ある程度プロパティに似ています。 プロパティと同様に、インデクサーの定義には get および set アクセサーを使用します。 ただし、プロパティは特定のデータメンバーを返すか設定しますが、インデクサーはオブジェクトインスタンスから特定の値を返すか設定します。 つまり、インスタンスデータを小さなパーツに分割し、各パーツにインデックスを付け、各パーツを取得または設定します。

プロパティを定義するには、プロパティ名を指定する必要があります。 インデクサーは名前ではなく、オブジェクトインスタンスを参照する this キーワードで定義されます。 次の例は、概念を示しています-

using System;

namespace IndexerApplication {

   class IndexedNames {
      private string[] namelist = new string[size];
      static public int size = 10;

      public IndexedNames() {
         for (int i = 0; i < size; i++)
         namelist[i] = "N. A.";
      }
      public string this[int index] {
         get {
            string tmp;

            if( index >= 0 && index <= size-1 ) {
               tmp = namelist[index];
            } else {
               tmp = "";
            }

            return ( tmp );
         }
         set {
            if( index >= 0 && index <= size-1 ) {
               namelist[index] = value;
            }
         }
      }
      static void Main(string[] args) {
         IndexedNames names = new IndexedNames();
         names[0] = "Zara";
         names[1] = "Riz";
         names[2] = "Nuha";
         names[3] = "Asif";
         names[4] = "Davinder";
         names[5] = "Sunil";
         names[6] = "Rubic";

         for ( int i = 0; i < IndexedNames.size; i++ ) {
            Console.WriteLine(names[i]);
         }
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Zara
Riz
Nuha
Asif
Davinder
Sunil
Rubic
N. A.
N. A.
N. A.

オーバーロードされたインデクサー

インデクサーは過負荷になる可能性があります。 インデクサーは複数のパラメーターで宣言することもでき、各パラメーターは異なるタイプである場合があります。 インデックスが整数である必要はありません。 C#では、文字列など、他のタイプのインデックスを使用できます。

次の例は、オーバーロードされたインデクサーを示しています-

using System;

namespace IndexerApplication {
   class IndexedNames {
      private string[] namelist = new string[size];
      static public int size = 10;

      public IndexedNames() {
         for (int i = 0; i < size; i++) {
            namelist[i] = "N. A.";
         }
      }
      public string this[int index] {
         get {
            string tmp;

            if( index >= 0 && index <= size-1 ) {
               tmp = namelist[index];
            } else {
               tmp = "";
            }

            return ( tmp );
         }
         set {
            if( index >= 0 && index <= size-1 ) {
               namelist[index] = value;
            }
         }
      }

      public int this[string name] {
         get {
            int index = 0;

            while(index < size) {
               if (namelist[index] == name) {
                return index;
               }
               index++;
            }
            return index;
         }
      }

      static void Main(string[] args) {
         IndexedNames names = new IndexedNames();
         names[0] = "Zara";
         names[1] = "Riz";
         names[2] = "Nuha";
         names[3] = "Asif";
         names[4] = "Davinder";
         names[5] = "Sunil";
         names[6] = "Rubic";

        //using the first indexer with int parameter
         for (int i = 0; i < IndexedNames.size; i++) {
            Console.WriteLine(names[i]);
         }

        //using the second indexer with the string parameter
         Console.WriteLine(names["Nuha"]);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Zara
Riz
Nuha
Asif
Davinder
Sunil
Rubic
N. A.
N. A.
N. A.
2

C#-デリゲート

C#デリゲートは、CまたはC ++の関数へのポインターに似ています。 delegate は、メソッドへの参照を保持する参照型変数です。 参照は実行時に変更できます。

デリゲートは、特にイベントとコールバックメソッドの実装に使用されます。 すべてのデリゲートは、暗黙的に System.Delegate クラスから派生します。

デリゲートの宣言

デリゲート宣言は、デリゲートが参照できるメソッドを決定します。 デリゲートは、デリゲートと同じ署名を持つメソッドを参照できます。

たとえば、デリゲートを考えます-

public delegate int MyDelegate (string s);

上記のデリゲートを使用して、単一の_string_パラメーターを持ち、_int_型変数を返すメソッドを参照できます。

デリゲート宣言の構文は-

delegate <return type> <delegate-name> <parameter list>

デリゲートのインスタンス化

デリゲートタイプが宣言されたら、デリゲートオブジェクトを new キーワードで作成し、特定のメソッドに関連付ける必要があります。 デリゲートを作成するとき、 new 式に渡される引数はメソッド呼び出しと同様に記述されますが、メソッドへの引数はありません。 たとえば-

public delegate void printString(string s);
...
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);

次の例は、整数パラメーターを受け取り、整数値を返すメソッドを参照するために使用できるデリゲートの宣言、インスタンス化、および使用を示しています。

using System;

delegate int NumberChanger(int n);
namespace DelegateAppl {

   class TestDelegate {
      static int num = 10;

      public static int AddNum(int p) {
         num += p;
         return num;
      }
      public static int MultNum(int q) {
         num *= q;
         return num;
      }
      public static int getNum() {
         return num;
      }
      static void Main(string[] args) {
        //create delegate instances
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);

        //calling the methods using the delegate objects
         nc1(25);
         Console.WriteLine("Value of Num: {0}", getNum());
         nc2(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Value of Num: 35
Value of Num: 175

デリゲートのマルチキャスト

デリゲートオブジェクトは、「+」演算子を使用して構成できます。 構成された代理人は、構成された2人の代理人を呼び出します。 同じタイプの代理人だけが構成できます。 「-」演算子を使用して、合成デリゲートからコンポーネントデリゲートを削除できます。

デリゲートのこのプロパティを使用すると、デリゲートが呼び出されたときに呼び出されるメソッドの呼び出しリストを作成できます。 これは、デリゲートの*マルチキャスト*と呼ばれます。 次のプログラムは、デリゲートのマルチキャストを示しています-

using System;

delegate int NumberChanger(int n);
namespace DelegateAppl {
   class TestDelegate {
      static int num = 10;

      public static int AddNum(int p) {
         num += p;
         return num;
      }
      public static int MultNum(int q) {
         num *= q;
         return num;
      }
      public static int getNum() {
         return num;
      }
      static void Main(string[] args) {
        //create delegate instances
         NumberChanger nc;
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);

         nc = nc1;
         nc += nc2;

        //calling multicast
         nc(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Value of Num: 75

デリゲートを使用する

次の例は、デリゲートの使用方法を示しています。 デリゲート_printString_を使用して、文字列を入力として受け取り、何も返さないメソッドを参照できます。

私たちはこのデリゲートを使用して2つのメソッドを呼び出します。最初のメソッドは文字列をコンソールに出力し、2番目のメソッドはそれをファイルに出力します-

using System;
using System.IO;

namespace DelegateAppl {

   class PrintString {
      static FileStream fs;
      static StreamWriter sw;

     //delegate declaration
      public delegate void printString(string s);

     //this method prints to the console
      public static void WriteToScreen(string str) {
         Console.WriteLine("The String is: {0}", str);
      }

     //this method prints to a file
      public static void WriteToFile(string s) {
         fs = new FileStream("c:\\message.txt",
         FileMode.Append, FileAccess.Write);
         sw = new StreamWriter(fs);
         sw.WriteLine(s);
         sw.Flush();
         sw.Close();
         fs.Close();
      }

     //this method takes the delegate as parameter and uses it to
     //call the methods as required
      public static void sendString(printString ps) {
         ps("Hello World");
      }

      static void Main(string[] args) {
         printString ps1 = new printString(WriteToScreen);
         printString ps2 = new printString(WriteToFile);
         sendString(ps1);
         sendString(ps2);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

The String is: Hello World

C#-イベント

  • イベント*は、キーを押す、クリックする、マウスを動かすなどのユーザーアクション、またはシステムが生成する通知などのイベントです。 アプリケーションは、発生したイベントに応答する必要があります。 たとえば、割り込み。 イベントはプロセス間通信に使用されます。

イベントでのデリゲートの使用

イベントはクラスで宣言および発生され、同じクラスまたは他のクラス内のデリゲートを使用してイベントハンドラーに関連付けられます。 イベントを含むクラスは、イベントを公開するために使用されます。 これは publisher クラスと呼ばれます。 このイベントを受け入れる他のクラスは subscriber クラスと呼ばれます。 イベントは publisher-subscriber モデルを使用します。

*publisher* は、イベントとデリゲートの定義を含むオブジェクトです。 イベントデリゲートの関連付けもこのオブジェクトで定義されます。 パブリッシャークラスオブジェクトはイベントを呼び出し、他のオブジェクトに通知されます。
*subscriber* は、イベントを受け入れ、イベントハンドラーを提供するオブジェクトです。 パブリッシャークラスのデリゲートは、サブスクライバークラスのメソッド(イベントハンドラー)を呼び出します。

イベントの宣言

クラス内でイベントを宣言するには、最初にイベントのデリゲート型を宣言する必要があります。 例えば、

public delegate string MyDel(string str);

次に、 event キーワードを使用して、イベント自体が宣言されます-

event MyDel MyEvent;

上記のコードは、_BoilerLogHandler_という名前のデリゲートと、_BoilerEventLog_という名前のイベントを定義します。このイベントは、デリゲートが発生したときに呼び出します。

using System;

namespace SampleApp {
   public delegate string MyDel(string str);

   class EventProgram {
      event MyDel MyEvent;

      public EventProgram() {
         this.MyEvent += new MyDel(this.WelcomeUser);
      }
      public string WelcomeUser(string username) {
         return "Welcome " + username;
      }
      static void Main(string[] args) {
         EventProgram obj1 = new EventProgram();
         string result = obj1.MyEvent("Tutorials Point");
         Console.WriteLine(result);
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Welcome Tutorials Point

C#-コレクション

コレクションクラスは、データの保存と取得のための特別なクラスです。 これらのクラスは、スタック、キュー、リスト、およびハッシュテーブルのサポートを提供します。 ほとんどのコレクションクラスは同じインターフェイスを実装します。

コレクションクラスは、メモリを要素に動的に割り当てたり、インデックスなどに基づいてアイテムのリストにアクセスするなど、さまざまな目的に使用されます。 これらのクラスは、C#のすべてのデータ型の基本クラスであるObjectクラスのオブジェクトのコレクションを作成します。

さまざまなコレクションクラスとその使用法

以下は、 System.Collection 名前空間で一般的に使用されるさまざまなクラスです。 詳細を確認するには、次のリンクをクリックしてください。

Sr.No. Class & Description and Useage
1

ArrayList

これは、オブジェクトの順序付けられたコレクションを表し、個別に*インデックスを付ける*ことができます。

基本的には配列の代替です。 ただし、配列とは異なり、 index を使用して指定された位置でリストの項目を追加および削除でき、配列は自動的にサイズ変更されます。 また、リスト内のアイテムの動的なメモリ割り当て、追加、検索、および並べ替えが可能です。

2

Hashtable

  • key* を使用して、コレクション内の要素にアクセスします。

ハッシュテーブルは、キーを使用して要素にアクセスする必要がある場合に使用され、有用なキー値を識別できます。 ハッシュテーブルの各アイテムには、*キー/値*のペアがあります。 キーは、コレクション内のアイテムにアクセスするために使用されます。

3

SortedList

リスト内のアイテムにアクセスするには、*キー*と*インデックス*を使用します。

ソートされたリストは、配列とハッシュテーブルの組み合わせです。 キーまたはインデックスを使用してアクセスできるアイテムのリストが含まれています。 インデックスを使用してアイテムにアクセスする場合、それはArrayListであり、キーを使用してアイテムにアクセスする場合、それはHashtableです。 アイテムのコレクションは常にキー値でソートされます。

4

Stack

これは、オブジェクトの「後入れ先出し」コレクションを表します。

アイテムの先入れ先出しアクセスが必要な場合に使用されます。 リストにアイテムを追加すると、そのアイテムは「プッシュ」と呼ばれ、削除すると「ポップ」と呼ばれます。

5

Queue

オブジェクトの「先入れ先出し」コレクションを表します。

アイテムの先入れ先出しアクセスが必要な場合に使用されます。 リストにアイテムを追加すると、それは enqueue と呼ばれ、アイテムを削除すると、 deque と呼ばれます。

6

BitArray

値1と0を使用して*バイナリ表現*の配列を表します。

ビットを保存する必要があるが、ビット数が事前にわからない場合に使用します。 ゼロから始まる*整数インデックス*を使用して、BitArrayコレクションのアイテムにアクセスできます。

C#-ジェネリック

*Generics* を使用すると、プログラムで実際に使用されるまで、クラスまたはメソッドのプログラミング要素のデータ型の仕様を定義できます。 つまり、ジェネリックを使用すると、任意のデータ型で機能するクラスまたはメソッドを作成できます。

データ型の代替パラメータを使用して、クラスまたはメソッドの仕様を記述します。 コンパイラは、クラスのコンストラクターまたはメソッドの関数呼び出しを検出すると、特定のデータ型を処理するコードを生成します。 簡単な例は、概念を理解するのに役立ちます-

using System;
using System.Collections.Generic;

namespace GenericApplication {
   public class MyGenericArray<T> {
      private T[] array;

      public MyGenericArray(int size) {
         array = new T[size + 1];
      }
      public T getItem(int index) {
         return array[index];
      }
      public void setItem(int index, T value) {
         array[index] = value;
      }
   }
   class Tester {
      static void Main(string[] args) {

        //declaring an int array
         MyGenericArray<int> intArray = new MyGenericArray<int>(5);

        //setting values
         for (int c = 0; c < 5; c++) {
            intArray.setItem(c, c*5);
         }

        //retrieving the values
         for (int c = 0; c < 5; c++) {
            Console.Write(intArray.getItem(c) + " ");
         }

         Console.WriteLine();

        //declaring a character array
         MyGenericArray<char> charArray = new MyGenericArray<char>(5);

        //setting values
         for (int c = 0; c < 5; c++) {
            charArray.setItem(c, (char)(c+97));
         }

        //retrieving the values
         for (int c = 0; c< 5; c++) {
            Console.Write(charArray.getItem(c) + " ");
         }
         Console.WriteLine();

         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

0 5 10 15 20
a b c d e

ジェネリックの機能

ジェネリックは、次の方法であなたのプログラムを豊かにする技術です-

  • コードの再利用、型の安全性、パフォーマンスを最大化するのに役立ちます。
  • ジェネリックコレクションクラスを作成できます。 .NET Frameworkクラスライブラリには、_System.Collections.Generic_名前空間にいくつかの新しいジェネリックコレクションクラスが含まれています。 _System.Collections_名前空間のコレクションクラスの代わりに、これらの汎用コレクションクラスを使用できます。
  • 独自の汎用インターフェイス、クラス、メソッド、イベント、デリゲートを作成できます。
  • 特定のデータ型のメソッドにアクセスできるように制限された汎用クラスを作成できます。 *リフレクションを使用して、実行時に汎用データ型で使用される型に関する情報を取得できます。

ジェネリックメソッド

前の例では、ジェネリッククラスを使用しました。型パラメーターを使用してジェネリックメソッドを宣言できます。 次のプログラムは、概念を示しています-

using System;
using System.Collections.Generic;

namespace GenericMethodAppl {
   class Program {
      static void Swap<T>(ref T lhs, ref T rhs) {
         T temp;
         temp = lhs;
         lhs = rhs;
         rhs = temp;
      }
      static void Main(string[] args) {
         int a, b;
         char c, d;
         a = 10;
         b = 20;
         c = 'I';
         d = 'V';

        //display values before swap:
         Console.WriteLine("Int values before calling swap:");
         Console.WriteLine("a = {0}, b = {1}", a, b);
         Console.WriteLine("Char values before calling swap:");
         Console.WriteLine("c = {0}, d = {1}", c, d);

        //call swap
         Swap<int>(ref a, ref b);
         Swap<char>(ref c, ref d);

        //display values after swap:
         Console.WriteLine("Int values after calling swap:");
         Console.WriteLine("a = {0}, b = {1}", a, b);
         Console.WriteLine("Char values after calling swap:");
         Console.WriteLine("c = {0}, d = {1}", c, d);

         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Int values before calling swap:
a = 10, b = 20
Char values before calling swap:
c = I, d = V
Int values after calling swap:
a = 20, b = 10
Char values after calling swap:
c = V, d = I

ジェネリックデリゲート

型パラメーターを使用して汎用デリゲートを定義できます。 たとえば-

delegate T NumberChanger<T>(T n);

次の例は、このデリゲートの使用を示しています-

using System;
using System.Collections.Generic;

delegate T NumberChanger<T>(T n);
namespace GenericDelegateAppl {
   class TestDelegate {
      static int num = 10;

      public static int AddNum(int p) {
         num += p;
         return num;
      }
      public static int MultNum(int q) {
         num* = q;
         return num;
      }
      public static int getNum() {
         return num;
      }
      static void Main(string[] args) {
        //create delegate instances
         NumberChanger<int> nc1 = new NumberChanger<int>(AddNum);
         NumberChanger<int> nc2 = new NumberChanger<int>(MultNum);

        //calling the methods using the delegate objects
         nc1(25);
         Console.WriteLine("Value of Num: {0}", getNum());

         nc2(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Value of Num: 35
Value of Num: 175

C#-無名メソッド

デリゲートは、デリゲートと同じシグネチャを持つメソッドを参照するために使用されることを説明しました。 つまり、デリゲートオブジェクトを使用して、デリゲートが参照できるメソッドを呼び出すことができます。

  • 匿名メソッド*は、コードブロックをデリゲートパラメーターとして渡す手法を提供します。 匿名メソッドは、名前のないメソッドであり、本文のみです。

無名メソッドで戻り値の型を指定する必要はありません。メソッド本体内のreturnステートメントから推測されます。

匿名メソッドを書く

匿名メソッドは、デリゲートインスタンスを作成し、 delegate キーワードで宣言します。 例えば、

delegate void NumberChanger(int n);
...
NumberChanger nc = delegate(int x) {
   Console.WriteLine("Anonymous Method: {0}", x);
};

コードブロック_Console.WriteLine( "Anonymous Method:\ {0}"、x); _は、匿名メソッドの本体です。

デリゲートは、匿名メソッドと名前付きメソッドの両方で同じ方法で、つまり、メソッドパラメータをデリゲートオブジェクトに渡すことで呼び出すことができます。

例えば、

nc(10);

次の例は、概念を示しています-

using System;

delegate void NumberChanger(int n);
namespace DelegateAppl {
   class TestDelegate {
      static int num = 10;

      public static void AddNum(int p) {
         num += p;
         Console.WriteLine("Named Method: {0}", num);
      }
      public static void MultNum(int q) {
         num *= q;
         Console.WriteLine("Named Method: {0}", num);
      }
      public static int getNum() {
         return num;
      }
      static void Main(string[] args) {
        //create delegate instances using anonymous method
         NumberChanger nc = delegate(int x) {
            Console.WriteLine("Anonymous Method: {0}", x);
         };

        //calling the delegate using the anonymous method
         nc(10);

        //instantiating the delegate using the named methods
         nc =  new NumberChanger(AddNum);

        //calling the delegate using the named methods
         nc(5);

        //instantiating the delegate using another named methods
         nc =  new NumberChanger(MultNum);

        //calling the delegate using the named methods
         nc(2);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Anonymous Method: 10
Named Method: 15
Named Method: 30

C#-安全でないコード

C#では、 unsafe 修飾子でマークされている場合、コードブロックの関数でポインター変数を使用できます。 *アンセーフコード*またはアンマネージコードは、*ポインター*変数を使用するコードブロックです。

'__ 注意-この章で言及されているプログラム(https://www.finddevguides.com/compile_csharp_online.php[codingground])を実行するには、_Project >>コンパイルオプション>>コンパイルコマンド_でコンパイルオプションを設定してください

`+ mcs * .cs -out:main.exe -unsafe" + ` '__

ポインタ

  • ポインタ*は、値が別の変数のアドレス、つまりメモリ位置の直接アドレスである変数です。 変数や定数と同様に、ポインターを宣言してから変数アドレスを保存する必要があります。

ポインタ宣言の一般的な形式は次のとおりです-

type *var-name;

以下は、有効なポインター宣言です-

int    *ip;   /*pointer to an integer*/
double *dp;   /*pointer to a double*/
float  *fp;   /*pointer to a float*/
char   *ch    /*pointer to a character*/

次の例は、安全でない修飾子を使用して、C#でのポインターの使用を示しています-

using System;

namespace UnsafeCodeApplication {
   class Program {
      static unsafe void Main(string[] args) {
         int var = 20;
         int* p = &var;

         Console.WriteLine("Data is: {0} ",  var);
         Console.WriteLine("Address is: {0}",  (int)p);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Data is: 20
Address is: 99215364

メソッド全体を安全でないと宣言する代わりに、コードの一部を安全でないと宣言することもできます。 次のセクションの例はこれを示しています。

ポインターを使用してデータ値を取得する

  • ToString()*メソッドを使用して、ポインター変数によって参照されるロケートに格納されているデータを取得できます。 次の例はこれを示しています-
using System;

namespace UnsafeCodeApplication {
   class Program {
      public static void Main() {
         unsafe {
            int var = 20;
            int* p = &var;

            Console.WriteLine("Data is: {0} " , var);
            Console.WriteLine("Data is: {0} " , p->ToString());
            Console.WriteLine("Address is: {0} " , (int)p);
         }
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Data is: 20
Data is: 20
Address is: 77128984

メソッドへのパラメーターとしてのポインターの受け渡し

パラメーターとしてメソッドにポインター変数を渡すことができます。 次の例はこれを示しています-

using System;

namespace UnsafeCodeApplication {
   class TestPointer {
      public unsafe void swap(int *p, int* q) {
         int temp = *p;
         *p = *q;
         *q = temp;
      }
      public unsafe static void Main() {
         TestPointer p = new TestPointer();
         int var1 = 10;
         int var2 = 20;
         int* x = &var1;
         int *y = &var2;

         Console.WriteLine("Before Swap: var1:{0}, var2: {1}", var1, var2);
         p.swap(x, y);

         Console.WriteLine("After Swap: var1:{0}, var2: {1}", var1, var2);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Before Swap: var1: 10, var2: 20
After Swap: var1: 20, var2: 10

ポインターを使用して配列要素にアクセスする

C#では、配列名と配列データと同じデータ型へのポインターは、同じ変数型ではありません。 たとえば、int* pとint [] pは同じ型ではありません。 ポインター変数pはメモリー内で固定されていないが、配列アドレスはメモリー内で固定されているため、インクリメントできません。

したがって、CまたはC ++で従来行っているように、ポインター変数を使用して配列データにアクセスする必要がある場合(リンク:/cprogramming/c_pointers [Cポインター]を確認してください)、* fixedを使用してポインターを修正する必要があります*キーワード。

次の例はこれを示しています-

using System;

namespace UnsafeCodeApplication {
   class TestPointer {
      public unsafe static void Main() {
         int[]  list = {10, 100, 200};
         fixed(int *ptr = list)

        /*let us have array address in pointer*/
         for ( int i = 0; i < 3; i++) {
            Console.WriteLine("Address of list[{0}]={1}",i,(int)(ptr + i));
            Console.WriteLine("Value of list[{0}]={1}", i, *(ptr + i));
         }

         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

Address of list[0] = 31627168
Value of list[0] = 10
Address of list[1] = 31627172
Value of list[1] = 100
Address of list[2] = 31627176
Value of list[2] = 200

安全でないコードのコンパイル

安全でないコードをコンパイルするには、コマンドラインコンパイラで /unsafe コマンドラインスイッチを指定する必要があります。

たとえば、安全でないコードを含むprog1.csという名前のプログラムをコマンドラインからコンパイルするには、コマンドを与えます-

csc/unsafe prog1.cs

Visual Studio IDEを使用している場合は、プロジェクトプロパティで安全でないコードの使用を有効にする必要があります。

これを行うには-

  • ソリューションエクスプローラーでプロパティノードをダブルクリックして、*プロジェクトプロパティ*を開きます。
  • [ビルド]タブをクリックします。
  • オプション「安全でないコードを許可」を選択します。

C#-マルチスレッド

  • スレッド*は、プログラムの実行パスとして定義されます。 各スレッドは、制御の一意のフローを定義します。 アプリケーションに複雑で時間のかかる操作が含まれる場合、各スレッドが特定のジョブを実行するように、異なる実行パスまたはスレッドを設定すると役立つことがよくあります。

スレッドは*軽量プロセス*です。 スレッドの一般的な使用例の1つは、最新のオペレーティングシステムによる並行プログラミングの実装です。 スレッドを使用すると、CPUサイクルの無駄が節約され、アプリケーションの効率が向上します。

ここまでで、アプリケーションの実行インスタンスである単一プロセスとして単一スレッドが実行されるプログラムを作成しました。 ただし、この方法では、アプリケーションは一度に1つのジョブを実行できます。 一度に複数のタスクを実行するために、より小さなスレッドに分割できます。

スレッドのライフサイクル

スレッドのライフサイクルは、System.Threading.Threadクラスのオブジェクトが作成されると開始され、スレッドが終了または実行を完了すると終了します。

以下は、スレッドのライフサイクルにおけるさまざまな状態です-

  • The Unstarted State -スレッドのインスタンスは作成されているが、Startメソッドが呼び出されていない状況です。
  • 準備完了状態-スレッドの実行準備ができており、CPUサイクルを待機している状態です。
  • 実行不可能な状態-スレッドが実行可能でない場合、
  • Sleepメソッドが呼び出されました
  • 待機メソッドが呼び出されました
  • I/O操作によってブロックされました
  • The Dead State -スレッドが実行を完了するか中止される状況です。

メインスレッド

C#では、スレッドの操作に System.Threading.Thread クラスが使用されます。 マルチスレッドアプリケーションで個々のスレッドを作成してアクセスできます。 プロセスで最初に実行されるスレッドは、*メイン*スレッドと呼ばれます。

C#プログラムが実行を開始すると、メインスレッドが自動的に作成されます。 Thread クラスを使用して作成されたスレッドは、メインスレッドの子スレッドと呼ばれます。 Threadクラスの CurrentThread プロパティを使用してスレッドにアクセスできます。

次のプログラムは、メインスレッドの実行を示しています-

using System;
using System.Threading;

namespace MultithreadingApplication {
   class MainThreadProgram {
      static void Main(string[] args) {
         Thread th = Thread.CurrentThread;
         th.Name = "MainThread";

         Console.WriteLine("This is {0}", th.Name);
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

This is MainThread

スレッドクラスのプロパティとメソッド

次の表は、最も一般的に使用される Thread クラスの properties を示しています-

Sr.No. Property & Description
1

CurrentContext

スレッドが実行されている現在のコンテキストを取得します。

2

CurrentCulture

現在のスレッドのカルチャを取得または設定します。

3

CurrentPrinciple

スレッドの現在のプリンシパルを取得または設定します(ロールベースのセキュリティ用)。

4

CurrentThread

現在実行中のスレッドを取得します。

5

CurrentUICulture

Resource Managerが実行時にカルチャ固有のリソースを検索するために使用する現在のカルチャを取得または設定します。

6

ExecutionContext

現在のスレッドのさまざまなコンテキストに関する情報を含むExecutionContextオブジェクトを取得します。

7

IsAlive

現在のスレッドの実行ステータスを示す値を取得します。

8

IsBackground

スレッドがバックグラウンドスレッドであるかどうかを示す値を取得または設定します。

9

IsThreadPoolThread

スレッドがマネージスレッドプールに属しているかどうかを示す値を取得します。

10

ManagedThreadId

現在のマネージスレッドの一意の識別子を取得します。

11

Name

スレッドの名前を取得または設定します。

12

Priority

スレッドのスケジューリング優先順位を示す値を取得または設定します。

13

ThreadState

現在のスレッドの状態を含む値を取得します。

次の表は、 Thread クラスで最も一般的に使用される methods の一部を示しています-

Sr.No. Method & Description
1

public void Abort()

呼び出されたスレッドでThreadAbortExceptionを発生させて、スレッドを終了するプロセスを開始します。 このメソッドを呼び出すと、通常、スレッドが終了します。

2

public static LocalDataStoreSlot AllocateDataSlot()

すべてのスレッドに名前のないデータスロットを割り当てます。 パフォーマンスを向上させるには、代わりにThreadStaticAttribute属性でマークされたフィールドを使用します。

3

public static LocalDataStoreSlot AllocateNamedDataSlot(string name)

すべてのスレッドに名前付きデータスロットを割り当てます。 パフォーマンスを向上させるには、代わりにThreadStaticAttribute属性でマークされたフィールドを使用します。

4

public static void BeginCriticalRegion()

スレッドの中止または未処理の例外の影響により、アプリケーションドメイン内の他のタスクが危険にさらされる可能性があるコードの領域に実行が入ろうとしていることをホストに通知します。

5

public static void BeginThreadAffinity()

マネージコードが現在の物理オペレーティングシステムスレッドのIDに依存する命令を実行しようとしていることをホストに通知します。

6

public static void EndCriticalRegion()

スレッドの中止または未処理の例外の影響が現在のタスクに制限されているコードの領域に実行が入ろうとしていることをホストに通知します。

7

public static void EndThreadAffinity()

マネージコードが現在の物理オペレーティングシステムスレッドのIDに依存する命令の実行を終了したことをホストに通知します。

8

public static void FreeNamedDataSlot(string name)

プロセス内のすべてのスレッドについて、名前とスロットの関連付けを削除します。 パフォーマンスを向上させるには、代わりにThreadStaticAttribute属性でマークされたフィールドを使用します。

9

public static Object GetData(LocalDataStoreSlot slot)

現在のスレッドの現在のドメイン内で、現在のスレッドの指定されたスロットから値を取得します。 パフォーマンスを向上させるには、代わりにThreadStaticAttribute属性でマークされたフィールドを使用します。

10

public static AppDomain GetDomain()

現在のスレッドが実行されている現在のドメインを返します。

11

public static AppDomain GetDomainID()

一意のアプリケーションドメイン識別子を返します

12

public static LocalDataStoreSlot GetNamedDataSlot(string name)

名前付きデータスロットを検索します。 パフォーマンスを向上させるには、代わりにThreadStaticAttribute属性でマークされたフィールドを使用します。

13

public void Interrupt()

WaitSleepJoinスレッド状態にあるスレッドを中断します。

14

public void Join()

標準のCOMおよびSendMessageのポンピングを実行しながら、スレッドが終了するまで呼び出し側のスレッドをブロックします。 このメソッドには、さまざまなオーバーロードフォームがあります。

15

public static void MemoryBarrier()

メモリアクセスを次のように同期します。現在のスレッドを実行しているプロセッサは、MemoryBarrierの呼び出しに続くメモリアクセスの後にMemoryBarrierの呼び出し前のメモリアクセスが実行されるような方法で命令を並べ替えることはできません。

16

public static void ResetAbort()

現在のスレッドに対して要求された中止をキャンセルします。

17

public static void SetData(LocalDataStoreSlot slot, Object data)

現在実行中のスレッドの指定されたスロットに、そのスレッドの現在のドメインのデータを設定します。 パフォーマンスを向上させるには、代わりにThreadStaticAttribute属性でマークされたフィールドを使用します。

18

public void Start()

スレッドを開始します。

19

public static void Sleep(int millisecondsTimeout)

スレッドを一定時間一時停止します。

20

public static void SpinWait(int iterations)

スレッドは、繰り返しパラメーターで定義された回数だけ待機します

21

public static byte VolatileRead(ref byte address)

  • public static double VolatileRead(ref double address)*
  • public static int VolatileRead(ref int address)*
  • public static Object VolatileRead(ref Object address) *

フィールドの値を読み取ります。 値は、プロセッサの数またはプロセッサキャッシュの状態に関係なく、コンピュータのプロセッサによって書き込まれた最新の値です。 このメソッドには、さまざまなオーバーロードフォームがあります。 上記の一部のみを示します。

22
  • public static void VolatileWrite(ref byte address,byte value)*
  • public static void VolatileWrite(ref double address、double value)*
  • public static void VolatileWrite(ref int address、int value)*
  • public static void VolatileWrite(refオブジェクトアドレス、オブジェクト値) *

値をすぐにフィールドに書き込み、その値がコンピューター内のすべてのプロセッサーから見えるようにします。 このメソッドには、さまざまなオーバーロードフォームがあります。 上記の一部のみを示します。

23
  • public static bool Yield()*

現在のプロセッサで実行する準備ができている別のスレッドに呼び出しスレッドを実行させます。 オペレーティングシステムは、譲るスレッドを選択します。

スレッドを作成する

スレッドは、Threadクラスを拡張することで作成されます。 次に、拡張Threadクラスは、* Start()*メソッドを呼び出して、子スレッドの実行を開始します。

次のプログラムは、概念を示しています-

using System;
using System.Threading;

namespace MultithreadingApplication {
   class ThreadCreationProgram {
      public static void CallToChildThread() {
         Console.WriteLine("Child thread starts");
      }
      static void Main(string[] args) {
         ThreadStart childref = new ThreadStart(CallToChildThread);
         Console.WriteLine("In Main: Creating the Child thread");
         Thread childThread = new Thread(childref);
         childThread.Start();
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

In Main: Creating the Child thread
Child thread starts

スレッドの管理

Threadクラスは、スレッドを管理するためのさまざまなメソッドを提供します。

次の例は、特定の期間スレッドを一時停止するための* sleep()*メソッドの使用を示しています。

using System;
using System.Threading;

namespace MultithreadingApplication {
   class ThreadCreationProgram {
      public static void CallToChildThread() {
         Console.WriteLine("Child thread starts");

        //the thread is paused for 5000 milliseconds
         int sleepfor = 5000;

         Console.WriteLine("Child Thread Paused for {0} seconds", sleepfor/1000);
         Thread.Sleep(sleepfor);
         Console.WriteLine("Child thread resumes");
      }

      static void Main(string[] args) {
         ThreadStart childref = new ThreadStart(CallToChildThread);
         Console.WriteLine("In Main: Creating the Child thread");

         Thread childThread = new Thread(childref);
         childThread.Start();
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

In Main: Creating the Child thread
Child thread starts
Child Thread Paused for 5 seconds
Child thread resumes

スレッドの破棄

  • Abort()*メソッドは、スレッドを破棄するために使用されます。

ランタイムは、 ThreadAbortException をスローしてスレッドを中止します。 この例外はキャッチできず、コントロールは_finally_ブロック(存在する場合)に送信されます。

次のプログラムはこれを示しています-

using System;
using System.Threading;

namespace MultithreadingApplication {
   class ThreadCreationProgram {
      public static void CallToChildThread() {
         try {
            Console.WriteLine("Child thread starts");

           //do some work, like counting to 10
            for (int counter = 0; counter <= 10; counter++) {
               Thread.Sleep(500);
               Console.WriteLine(counter);
            }

            Console.WriteLine("Child Thread Completed");
         } catch (ThreadAbortException e) {
            Console.WriteLine("Thread Abort Exception");
         } finally {
            Console.WriteLine("Couldn't catch the Thread Exception");
         }
      }
      static void Main(string[] args) {
         ThreadStart childref = new ThreadStart(CallToChildThread);
         Console.WriteLine("In Main: Creating the Child thread");

         Thread childThread = new Thread(childref);
         childThread.Start();

        //stop the main thread for some time
         Thread.Sleep(2000);

        //now abort the child
         Console.WriteLine("In Main: Aborting the Child thread");

         childThread.Abort();
         Console.ReadKey();
      }
   }
}

上記のコードをコンパイルして実行すると、次の結果が生成されます-

In Main: Creating the Child thread
Child thread starts
0
1
2
In Main: Aborting the Child thread
Thread Abort Exception
Couldn't catch the Thread Exception

Csharp-questions-answers