次の方法で共有


C# のメソッド

メソッドは、一連のステートメントが含まれているコード ブロックです。 必要なメソッド引数を指定してプログラムからメソッドを呼び出すと、メソッド内のステートメントが実行されます。 C# では、実行されるすべての命令がメソッドのコンテキストで実行されます。

Note

このトピックでは、名前付きメソッドについて説明します。 匿名関数について詳しくは、「ラムダ式」をご覧ください。

メソッド シグネチャ

メソッドは、次の項目を指定することにより、classrecord、または struct で宣言されます。

  • publicprivate など、任意のアクセス レベル。 既定値は、private です。
  • abstractsealed など、任意の修飾子。
  • メソッドに何も与えられていない場合、戻り値または void
  • メソッド名。
  • メソッド パラメーター。 メソッド パラメーターはかっこで囲み、各パラメーターをコンマで区切ります。 かっこ内を空にすると、メソッドでパラメーターが不要なことを意味します。

これらのまとまりがメソッド シグネチャとなります。

重要

メソッドのオーバーロードを可能にするために、メソッドの戻り値の型はメソッドのシグネチャには含まれません。 ただし、デリゲートとそれが指すメソッドの互換性を決定する場合には、メソッドのシグネチャの一部となります。

次の例では、5 つのメソッドを含む Motorcycle という名前のクラスを定義します。

namespace MotorCycleExample
{
    abstract class Motorcycle
    {
        // Anyone can call this.
        public void StartEngine() {/* Method statements here */ }

        // Only derived classes can call this.
        protected void AddGas(int gallons) { /* Method statements here */ }

        // Derived classes can override the base class implementation.
        public virtual int Drive(int miles, int speed) { /* Method statements here */ return 1; }

        // Derived classes can override the base class implementation.
        public virtual int Drive(TimeSpan time, int speed) { /* Method statements here */ return 0; }

        // Derived classes must implement this.
        public abstract double GetTopSpeed();
    }

Motorcycle クラスにオーバーロードされたメソッド Drive が含まれています。 2 つのメソッドは同じ名前ですが、パラメーターの型で区別されます。

メソッドの呼び出し

メソッドはインスタンスまたは静的になります。 オブジェクトをインスタンス化し、そのインスタンスでインスタンス メソッドを呼び出す必要があります。インスタンス メソッドは、そのインスタンスとそのデータに対して動作します。 メソッドが属する型の名前を参照して静的メソッドを呼び出します。静的メソッドではインスタンス データは操作できません。 オブジェクト インスタンス経由で静的メソッドを呼び出そうとすると、コンパイラ エラーが発生します。

メソッドを呼び出すことは、フィールドにアクセスするのと似ています。 オブジェクトの名前 (インスタンス メソッドを呼び出す場合) または型の名前 (static メソッドを呼び出す場合) の後ろに、期間、メソッドの名前、かっこを追加します。 引数はかっこの中に記述し、コンマで区切ります。

メソッド定義には、必要なパラメーターの名前と型を指定します。 呼び出し元からメソッドを呼び出すとき、各パラメーターに引数と呼ばれる具体的な値を指定します。 引数にはパラメーター型との互換性が必要ですが、呼び出し元のコードで引数名を使用する場合、引数名がメソッドで定義されるパラメーター名と同じである必要はありません。 次の例では、Square メソッドに型が inti という名前のパラメーターが 1 つ含まれています。 最初のメソッド呼び出しでは、型が Squareint という名前の変数が メソッドに渡されます。2 つ目のメソッド呼び出しでは数値定数が、3 つ目のメソッド呼び出しでは式が渡されます。

public static class SquareExample
{
    public static void Main()
    {
        // Call with an int variable.
        int num = 4;
        int productA = Square(num);

        // Call with an integer literal.
        int productB = Square(12);

        // Call with an expression that evaluates to int.
        int productC = Square(productA * 3);
    }

    static int Square(int i)
    {
        // Store input argument in a local variable.
        int input = i;
        return input * input;
    }
}

メソッド呼び出しの最も一般的な形式では、位置引数が使用されます。これはメソッド パラメーターと同じ順序で引数を指定するものです。 そのため、Motorcycle クラスのメソッドは次の例のように呼び出されます。 たとえば、Drive メソッドの呼び出しには 2 つの引数が含まれます。この 2 つの引数は、メソッドの構文の 2 つのパラメーターに対応しています。 1 つ目は、miles パラメーターの値になります。 2 つ目は、speed パラメーターの値になります。

class TestMotorcycle : Motorcycle
{
    public override double GetTopSpeed() => 108.4;

    static void Main()
    {
        var moto = new TestMotorcycle();

        moto.StartEngine();
        moto.AddGas(15);
        _ = moto.Drive(5, 20);
        double speed = moto.GetTopSpeed();
        Console.WriteLine("My top speed is {0}", speed);
    }
}

メソッドを呼び出すとき、位置引数の代わりに名前付き引数を使用することもできます。 名前付き引数を使用するとき、パラメーター名に続けてコロン (":") と引数を指定します。 必要なすべての引数が存在する限り、メソッドの引数の順序は問われません。 次の例では、名前付き引数を使用して TestMotorcycle.Drive メソッドを呼び出しています。 この例では、メソッドのパラメーター リストとは反対の順序で名前付き引数が渡されています。

namespace NamedMotorCycle;

class TestMotorcycle : Motorcycle
{
    public override int Drive(int miles, int speed) =>
        (int)Math.Round((double)miles / speed, 0);

    public override double GetTopSpeed() => 108.4;

    static void Main()
    {
        var moto = new TestMotorcycle();
        moto.StartEngine();
        moto.AddGas(15);
        int travelTime = moto.Drive(miles: 170, speed: 60);
        Console.WriteLine("Travel time: approx. {0} hours", travelTime);
    }
}
// The example displays the following output:
//      Travel time: approx. 3 hours

位置引数と名前付き引数の両方を利用してメソッドを呼び出すことができます。 ただし、位置引数は、名前付き引数が正しい位置にある場合にのみ、名前付き引数に従うことができます。 次の例では、前の例にあった TestMotorcycle.Drive メソッドを呼び出していますが、位置引数が 1 つ、名前付き引数が 1 つ使用されています。

int travelTime = moto.Drive(170, speed: 55);

継承されたメソッドとオーバーライドされたメソッド

型に明示的に定義されるメンバーに加え、型は、その基底クラスに定義されているメンバーを継承します。 マネージド型という系統のすべての型は Object クラスから直接的または間接的に継承するため、すべての型が、Equals(Object)GetType()ToString() など、そのメンバーを継承します。 次の例では、Person クラスを定義し、2 つの Person オブジェクトをインスタンス化し、Person.Equals メソッドを呼び出して 2 つのオブジェクトが等しいかどうかを判断します。 ただし、Equals メソッドは Person クラスに定義されていません。Object から継承されたものです。

public class Person
{
    public string FirstName = default!;
}

public static class ClassTypeExample
{
    public static void Main()
    {
        Person p1 = new() { FirstName = "John" };
        Person p2 = new() { FirstName = "John" };
        Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));
    }
}
// The example displays the following output:
//      p1 = p2: False

型は継承されたメンバーをオーバーライドできます。override キーワードを使用し、オーバーライドされたメソッドを実装します。 メソッドのシグネチャは、オーバーライドされるメソッドと同じである必要があります。 次の例は前の例と似ていますが、Equals(Object) メソッドをオーバーライドしている点が異なります。 (この 2 つのメソッドは一貫性のある結果を提供するため、GetHashCode() メソッドもオーバーライドされます。)

namespace methods;

public class Person
{
    public string FirstName = default!;

    public override bool Equals(object? obj) =>
        obj is Person p2 &&
        FirstName.Equals(p2.FirstName);

    public override int GetHashCode() => FirstName.GetHashCode();
}

public static class Example
{
    public static void Main()
    {
        Person p1 = new() { FirstName = "John" };
        Person p2 = new() { FirstName = "John" };
        Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));
    }
}
// The example displays the following output:
//      p1 = p2: True

パラメーターを渡す

C# の型は、値型参照型のどちらかに区別されます。 組み込みの値型の一覧については、に関するページを参照してください。 既定では、値型と参照型のどちらも、値によってメソッドに渡されます。

パラメーターを値で渡す

値型が値でメソッドに渡されるとき、オブジェクト自体の代わりにオブジェクトのコピーがメソッドに渡されます。 そのため、呼び出されたメソッドでオブジェクトに加えた変更は、コントロールが呼び出し元に戻ったとき、元のオブジェクトで反映されません。

次の例では、値型を値でメソッドに渡します。呼び出されたメソッドが値型の値を変更しようとします。 型 int (値型) の変数を定義し、その値を 20 に初期化し、ModifyValue という名前のメソッドに値を渡します。このメソッドは変数の値を 30 に変更します。 しかしながら、メソッドが戻ると、変数の値は元のままです。

public static class ByValueExample
{
    public static void Main()
    {
        var value = 20;
        Console.WriteLine("In Main, value = {0}", value);
        ModifyValue(value);
        Console.WriteLine("Back in Main, value = {0}", value);
    }

    static void ModifyValue(int i)
    {
        i = 30;
        Console.WriteLine("In ModifyValue, parameter value = {0}", i);
        return;
    }
}
// The example displays the following output:
//      In Main, value = 20
//      In ModifyValue, parameter value = 30
//      Back in Main, value = 20

参照型のオブジェクトが値でメソッドに渡されると、オブジェクトへの参照が値で渡されます。 つまり、メソッドは、オブジェクト自体ではなく、オブジェクトの場所を示す引数を受け取ります。 この参照を使用してオブジェクトのメンバーを変更した場合、コントロールが呼び出し元のメソッドに戻ると、オブジェクトで変更が反映されています。 ただし、メソッドに渡されるオブジェクトを置換しても、コントロールが呼び出し元に戻ったとき、元のオブジェクトで反映されません。

次の例では、SampleRefType という名前のクラス (参照型) を定義します。 SampleRefType オブジェクトをインスタンス化し、その value フィールドに 44 を割り当て、ModifyObject メソッドにオブジェクトを渡します。 この例は、基本的に前の例と同様に、引数を値でメソッドに渡しています。 ただし、参照型を使用しているため、結果は異なります。 ModifyObjectobj.value フィールドを変更したことで、value メソッドの引数 rtMain フィールドも 33 に変更されます。例の出力で確認できます。

public class SampleRefType
{
    public int value;
}

public static class ByRefTypeExample
{
    public static void Main()
    {
        var rt = new SampleRefType { value = 44 };
        ModifyObject(rt);
        Console.WriteLine(rt.value);
    }

    static void ModifyObject(SampleRefType obj) => obj.value = 33;
}

パラメーターの参照渡し

メソッドの引数の値を変更し、コントロールが呼び出し元に戻ったときにその変更を反映させるには、参照でパラメーターを渡します。 パラメーターを参照で渡すには、キーワードの ref または out を使用します。 値を参照で渡すことで、コピーを回避することもできますが、in キーワードを使用して変更を防ぐこともできます。

次の例は、値が参照によって ModifyValue メソッドに渡される点を除き、前の例と同じです。 パラメーターの値が ModifyValue メソッドで変更されると、コントロールが呼び出し元に戻ったとき、地の変更が反映されます。

public static class ByRefExample
{
    public static void Main()
    {
        var value = 20;
        Console.WriteLine("In Main, value = {0}", value);
        ModifyValue(ref value);
        Console.WriteLine("Back in Main, value = {0}", value);
    }

    private static void ModifyValue(ref int i)
    {
        i = 30;
        Console.WriteLine("In ModifyValue, parameter value = {0}", i);
        return;
    }
}
// The example displays the following output:
//      In Main, value = 20
//      In ModifyValue, parameter value = 30
//      Back in Main, value = 30

参照型パラメーターを利用する典型的なパターンが変数の値の入れ替えです。 参照でメソッドに 2 つの変数を渡すと、メソッドがその中身を入れ替えます。 次の例では、整数値が入れ替えられます。


public static class RefSwapExample
{
    static void Main()
    {
        int i = 2, j = 3;
        Console.WriteLine("i = {0}  j = {1}", i, j);

        Swap(ref i, ref j);

        Console.WriteLine("i = {0}  j = {1}", i, j);
    }

    static void Swap(ref int x, ref int y) =>
        (y, x) = (x, y);
}
// The example displays the following output:
//      i = 2  j = 3
//      i = 3  j = 2

参照型パラメーターを渡すことで、個々の要素またはフィールドの値ではなく、参照自体の値を変更できます。

パラメーター コレクション

メソッドに厳密な数の引数を指定する要件が限定的になることがあります。 params キーワードを使って、パラメーターがパラメーター コレクションであることを示すと、可変数の引数を使ってメソッドを呼び出せるようにすることができます。 params キーワードでタグが付けられたパラメーターはコレクション型である必要があり、メソッドのパラメーター リストの最後のパラメーターである必要があります。

呼び出し元は、params パラメーターについて次の 4 つの方法のいずれかでメソッドを呼び出すことができます。

  • 必要な数の要素を含む、適切な型のコレクションを渡す。 例では、コンパイラが適切なコレクション型を作成するようにコレクション式を使っています。
  • 適切な型の引数をコンマで区切った一覧をメソッドに渡す。 コンパイラが適切なコレクション型を作成します。
  • null を渡す。
  • パラメーター コレクションに引数を指定しない。

次の例では、パラメーター コレクションからすべての母音を返す GetVowels という名前のメソッドを定義しています。 Main メソッドには、メソッド呼び出しの 4 つの方法すべてが入っています。 呼び出し元は、params 修飾子が含まれるパラメーターに引数を指定する必要はありません。 その場合、パラメーターは空のコレクションになります。

static class ParamsExample
{
    static void Main()
    {
        string fromArray = GetVowels(["apple", "banana", "pear"]);
        Console.WriteLine($"Vowels from collection expression: '{fromArray}'");

        string fromMultipleArguments = GetVowels("apple", "banana", "pear");
        Console.WriteLine($"Vowels from multiple arguments: '{fromMultipleArguments}'");

        string fromNull = GetVowels(null);
        Console.WriteLine($"Vowels from null: '{fromNull}'");

        string fromNoValue = GetVowels();
        Console.WriteLine($"Vowels from no value: '{fromNoValue}'");
    }

    static string GetVowels(params IEnumerable<string>? input)
    {
        if (input == null || !input.Any())
        {
            return string.Empty;
        }

        char[] vowels = ['A', 'E', 'I', 'O', 'U'];
        return string.Concat(
            input.SelectMany(
                word => word.Where(letter => vowels.Contains(char.ToUpper(letter)))));
    }
}

// The example displays the following output:
//     Vowels from array: 'aeaaaea'
//     Vowels from multiple arguments: 'aeaaaea'
//     Vowels from null: ''
//     Vowels from no value: ''

C# 13 より前の params 修飾子は、1 次元配列でのみ使用できます。

省略可能なパラメーターと引数

メソッド定義では、そのパラメーターが必須であるか、任意であるかを指定できます。 既定では、パラメーターは必須です。 省略可能なパラメーターを指定するには、メソッド定義にパラメーターの既定値を追加します。 メソッドが呼び出されるとき、省略可能なパラメーターに引数が指定されていなければ、既定値が代わりに使用されます。

パラメーターの既定値には、次のいずれかの種類の式を割り当てます。

  • リテラル文字列や数値など、定数。

  • default(SomeType) 形式の式。SomeType には値型または参照型を指定できます。 参照型の場合は、null を指定するのと実質的に同じです。 コンパイラでパラメーターの宣言から型を推論できるため、default リテラルを使用できます。

  • new ValType() が値型となる、ValType 形式の式。 この式は、値型の暗黙のパラメーターなしコンストラクターを呼び出し、それは型の実際のメンバーではありません。

    Note

    フォーム new ValType() の式が値型の明示的に定義されたパラメーターなしのコンストラクターを呼び出すと、既定のパラメーター値がコンパイル時定数である必要があります。コンパイラによってエラーが生成されます。 default(ValType) 式または default リテラルを使用して、パラメーターの既定値を指定します。 パラメーターなしのコンストラクターの詳細については、「構造体型」の記事の構造体の初期化と既定値に関するセクションを参照してください。

メソッドに必須のパラメーターと省略可能なパラメーターの両方が含まれる場合、省略可能なパラメーターはパラメーター リストの終わりに定義されます (すべての必須パラメーターの後に)。

次の例では、ExampleMethod メソッドを定義しています。必須のパラメーターが 1 つ、省略可能なパラメーターが 2 つあります。

public class Options
{
    public void ExampleMethod(int required, int optionalInt = default,
                              string? description = default)
    {
        var msg = $"{description ?? "N/A"}: {required} + {optionalInt} = {required + optionalInt}";
        Console.WriteLine(msg);
    }
}

呼び出し元は、引数を指定する最後の省略可能なパラメーターまで、すべての省略可能なパラメーターの引数を指定する必要があります。 たとえば、ExampleMethod メソッドでは、呼び出し元が description パラメーターの引数を指定する場合は、optionalInt パラメーターも指定する必要があります。 opt.ExampleMethod(2, 2, "Addition of 2 and 2"); は有効なメソッド呼び出しです。opt.ExampleMethod(2, , "Addition of 2 and 0"); は、"引数がありません" というコンパイラ エラーを発生させます。

メソッドが名前付き引数または位置引数と名前付き引数の組み合わせで呼び出される場合、呼び出し元は、メソッド呼び出しの最後の位置引数の後に続く引数を省略できます。

次の例では、ExampleMethod メソッドが 3 回呼び出されます。 最初の 2 つのメソッド呼び出しでは、位置引数が使用されます。 最初の呼び出しではいずれの省略可能なパラメーターも省略され、2 つ目の呼び出しでは最後の引数が省略されます。 3 つ目のメソッドは必須パラメーターの位置引数を指定しますが、名前付き引数を利用して description パラメーターに値を指定します。optionalInt パラメーターは省略します。

public static class OptionsExample
{
    public static void Main()
    {
        var opt = new Options();
        opt.ExampleMethod(10);
        opt.ExampleMethod(10, 2);
        opt.ExampleMethod(12, description: "Addition with zero:");
    }
}
// The example displays the following output:
//      N/A: 10 + 0 = 10
//      N/A: 10 + 2 = 12
//      Addition with zero:: 12 + 0 = 12

省略可能なパラメーターを使うと、"オーバーロードの解決"、つまりメソッド呼び出しに対して呼び出すオーバーロードを C# コンパイラが決定する方法に、次のような影響を与えます。

  • メソッド、インデクサー、またはコンストラクターは、それぞれのパラメーターが名前または位置によって 1 つの引数に対応していて、その引数をパラメーターの型に変換できる場合、実行の候補になります。
  • 複数の候補が見つかった場合、明示的に指定される引数には、優先変換に関するオーバーロード解決の規則が適用されます。 任意のパラメーターの省略された引数は無視されます。
  • 2 つの候補が等しく良好であると判断された場合、呼び出しで引数が省略された省略可能なパラメーターのない候補が優先されます。

戻り値

メソッドは、呼び出し元に値を返すことができます。 戻り値の型 (メソッド名の前に記述されている型) が void でない場合、メソッドは、return キーワードを使用して値を返すことができます。 return キーワードの後に、戻り値と一致する型の変数、定数、または式が記述されているステートメントは、その値をメソッドの呼び出し元に返します。 戻り値の型が void 以外のメソッドで値を返すには、return キーワードを使う必要があります。 また、 return キーワードは、メソッドの実行を中止します。

戻り値の型が voidの場合、値を持たない return ステートメントは、メソッドの実行を中止するときに役立ちます。 return キーワードを使わないと、メソッドは、コード ブロックの最後に到達した時点で実行を停止します。

たとえば、次の 2 つのメソッドは、 return キーワードを使用して整数を返します。

class SimpleMath
{
    public int AddTwoNumbers(int number1, int number2) =>
        number1 + number2;

    public int SquareANumber(int number) =>
        number * number;
}

上記の例は、式形式のメンバーです。 式形式のメンバーは、式によって返される値を返します。

以下のようにステートメント本文と return ステートメントを使用してメソッドを定義することを選択することもできます。

class SimpleMathExtnsion
{
    public int DivideTwoNumbers(int number1, int number2)
    {
        return number1 / number2;
    }
}

メソッドから返された値を使用する場合、呼び出し元のメソッド内で同じ型の値を使用している場所では、メソッド呼び出し自体を値として使用できます。 戻り値は、変数に代入することもできます。 たとえば、以下の 3 つのコードでは、同様の目的を達成できます。

int result = obj.AddTwoNumbers(1, 2);
result = obj.SquareANumber(result);
// The result is 9.
Console.WriteLine(result);
result = obj.SquareANumber(obj.AddTwoNumbers(1, 2));
// The result is 9.
Console.WriteLine(result);
result = obj2.DivideTwoNumbers(6,2);
// The result is 3.
Console.WriteLine(result);

メソッドで複数の値を返すと便利な場合があります。 複数の値を返すには、"タプル型" と "タプル リテラル" を使います。 タプル型は、タプルの要素のデータ型を決定します。 タプル リテラルは、返されたタプルの実際の値を提供します。 次の例の (string, string, string, int) では、GetPersonalInfo メソッドによって返されるタプル型が定義されています。 式 (per.FirstName, per.MiddleName, per.LastName, per.Age) はタプル リテラルです。このメソッドは、PersonInfo オブジェクトの名、ミドルネーム、姓、年齢を返します。

public (string, string, string, int) GetPersonalInfo(string id)
{
    PersonInfo per = PersonInfo.RetrieveInfoById(id);
    return (per.FirstName, per.MiddleName, per.LastName, per.Age);
}

その後、呼び出し元は、次のコードを使って、返されたタプルを使用できます。

var person = GetPersonalInfo("111111111");
Console.WriteLine($"{person.Item1} {person.Item3}: age = {person.Item4}");

名前は、タプル型の定義のタプル要素に割り当てることもできます。 次の例は、名前付き要素を使用する GetPersonalInfo メソッドの別バージョンです。

public (string FName, string MName, string LName, int Age) GetPersonalInfo(string id)
{
    PersonInfo per = PersonInfo.RetrieveInfoById(id);
    return (per.FirstName, per.MiddleName, per.LastName, per.Age);
}

この例の GetPersonalInfo メソッドの呼び出しは次のように変更できます。

var person = GetPersonalInfo("111111111");
Console.WriteLine($"{person.FName} {person.LName}: age = {person.Age}");

メソッドがパラメーターとして配列を受け取り、個々の要素の値を変更する場合、メソッドが配列を返す必要はありません。 C# では、すべての参照型は値で渡され、配列参照の値はその配列へのポインターです。 次の例では、values メソッドで行われた DoubleValues 配列の内容の変更を、配列の参照があるあらゆるコードで観察できます。


public static class ArrayValueExample
{
    static void Main()
    {
        int[] values = [2, 4, 6, 8];
        DoubleValues(values);
        foreach (var value in values)
        {
            Console.Write("{0}  ", value);
        }
    }

    public static void DoubleValues(int[] arr)
    {
        for (var ctr = 0; ctr <= arr.GetUpperBound(0); ctr++)
        {
            arr[ctr] *= 2;
        }
    }
}
// The example displays the following output:
//       4  8  12  16

拡張メソッド

通常、既存の型にメソッドを追加する方法が 2 つあります。

  • その型のソース コードを変更する。 メソッドをサポートするためにプライベート データ フィールドも追加した場合、ソースを変更すると破壊的変更が発生します。
  • 派生クラスで新しいメソッドを定義する。 構造体や列挙型など、その他の型の継承を利用し、メソッドをこの方法で追加することはできません。 シール クラスにメソッドを "追加する" こともできません。

拡張メソッドでは、型自体を変更せずに、あるいは継承された型に新しいメソッドを実装せずに、既存の型にメソッドを "追加" できます。 また、拡張メソッドは、それが拡張する型と同じアセンブリに置く必要がありません。 型の定義済みメンバーのように拡張メソッドを呼び出します。

詳細については、「拡張メソッド」を参照してください。

非同期メソッド

非同期機能を使用することによって、明示的なコールバックを使用せずに、または複数のメソッドやラムダ式にわたって手動でコードを分割することなく、非同期メソッドを呼び出すことができます。

メソッドに async 修飾子を付けると、そのメソッドで await 演算子を使用できます。 コントロールが非同期メソッドの await 式に到達すると、待機中のタスクが完了していない場合、コントロールが呼び出し元に戻ります。await キーワードが与えられたメソッドの進行は、待機中のタスクが完了するまで中断されます。 タスクが完了すると、メソッドで実行を再開できます。

Note

非同期メソッドは、まだ完了していない待機中の最初のオブジェクトに達するか、または非同期メソッドの最後に達すると、呼び出し元に戻ります。

非同期メソッドの戻り値の型は、一般に、Task<TResult>TaskIAsyncEnumerable<T>、または void になります。 戻り値の型 void は主として、戻り値の型 void が必要なイベント ハンドラーの定義に使用されます。 void を返す非同期メソッドは待機できません。void を返すメソッドの呼び出し元は、このメソッドがスローする例外をキャッチできません。 非同期メソッドでは、タスクと同様の戻り値の型を持つことができます。

次の例では、DelayAsync は、整数を返す return ステートメントのある非同期メソッドです。 非同期メソッドであるため、そのメソッド宣言で戻り値の型 Task<int> を指定する必要があります。 戻り値の型が Task<int>であるため、次のステートメント await に示すように、DoSomethingAsync 内の int result = await delayTask 式を評価すると整数が生成されます。

class Program
{
    static Task Main() => DoSomethingAsync();

    static async Task DoSomethingAsync()
    {
        Task<int> delayTask = DelayAsync();
        int result = await delayTask;

        // The previous two statements may be combined into
        // the following statement.
        //int result = await DelayAsync();

        Console.WriteLine($"Result: {result}");
    }

    static async Task<int> DelayAsync()
    {
        await Task.Delay(100);
        return 5;
    }
}
// Example output:
//   Result: 5

非同期メソッドで inrefout パラメーターを宣言することはできませんが、これらのパラメーターを持つメソッドを呼び出すことはできます。

非同期メソッドの詳細については、「async および await を使用した非同期プログラミング」と非同期の戻り値の型に関するページを参照してください。

式形式のメンバー

メソッドの定義としては、式の結果ですぐに戻るか、メソッドの本体として 1 つのステートメントを含むものが一般的です。 => を使用してこのようなメソッドを定義するための構文ショートカットがあります。

public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
public void Print() => Console.WriteLine(First + " " + Last);
// Works with operators, properties, and indexers too.
public static Complex operator +(Complex a, Complex b) => a.Add(b);
public string Name => First + " " + Last;
public Customer this[long id] => store.LookupCustomer(id);

メソッドが void を返すか、非同期メソッドである場合は、メソッドの本文を (ラムダの場合と同様に) ステートメント式にする必要があります。 プロパティとインデクサーは読み取り専用にする必要があるため、get アクセサー キーワードは使用しないでください。

Iterators

反復子は、リストや配列など、コレクションに対するカスタム イテレーションを実行します。 反復子は、 yield return ステートメントを使用して、各要素を 1 回に1 つ返します。 yield return ステートメントに到達すると、現在の場所が記録されます。呼び出し元は、シーケンス内の次の要素を要求できます。

反復子の戻り値の型は、IEnumerableIEnumerable<T>IAsyncEnumerable<T>IEnumerator、または IEnumerator<T> にすることができます。

詳細については、「 反復子」を参照してください。

関連項目