3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C#の分解と式形式のコンストラクタの組み合わせ

Last updated at Posted at 2019-03-17

C# 7.0ではこんなコードが書けます。

public class Person
{
    public string FirstName { get; }
    public string LastName { get; }

    public Person(string firstName, string lastName)
        => (FirstName, LastName) = (firstName, lastName);
}

これは、C# 7.0から入った

を使ったコードです。

これを使わないコードだと、こうなります。

public Person {
    public string FirstName { get; }
    public string LastName { get; }

    public Person(string firstName, string lastName)
    {
        this.FirstName = firstName;
        this.LastName = lastName;
    }
}

分解式形式のコンストラクタを使っても、そんなに可読性は変わらないと思うので、お好みで。

ただ、MSの公式ドキュメントに使ったコード例があるので、読めるようにはしておいたほうがいいでしょう。

ちなみに、C# 6.0から入ったゲッターオンリーのプロパティーも使っています。これを使わないとしたらだいたいこんな感じに。

public class Person
{
    public string FirstName { get { return firstName; } }
    private readonly string firstName;

    public string LastName { get { return lastName; } }
    private readonly string lastName;

    public PersonOld(string firstName, string lastName)
    {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

内部的にValueTupleは作られない

「分解」と「式形式のコンストラクタ」を使ったコードては、一見ValueTupleを生成しているように読めます。

using System;

public class Person
{
    public string FirstName { get; }
    public string LastName { get; }

    public Person(string firstName, string lastName)
        => (FirstName, LastName) = (firstName, lastName);
}

SharpLabを使って、C# => IL => DecompileしたC#のコードは次の通り。

コードのコンストラクタを見ると、ValueTupleが作成されていません。

using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
public class Person
{
    [CompilerGenerated]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private readonly string <FirstName>k__BackingField;

    [CompilerGenerated]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private readonly string <LastName>k__BackingField;

    public string FirstName
    {
        [CompilerGenerated]
        get
        {
            return <FirstName>k__BackingField;
        }
    }

    public string LastName
    {
        [CompilerGenerated]
        get
        {
            return <LastName>k__BackingField;
        }
    }

    public Person(string firstName, string lastName)
    {
        <FirstName>k__BackingField = firstName;
        <LastName>k__BackingField = lastName;
    }
}

これはC# 7.1から変更が入ったそうです。これについては、こちらのツイートから辿れる会話もぜひ確認してみてください。

ありがとうございました。

余談

レコードが欲しい・・・

参考リンク

GitHubの関連ありそうなissueやドキュメントはこちら。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?