如何有效地实现不可变类型

时间:2011-08-29 22:58:51

标签: c# c#-4.0

编码C#时,我经常发现自己实现了不可变类型。 我总是写完了很多代码,我想知道是否有更快的方法来实现它。

我通常写的是:

public struct MyType
{
  private Int32 _value;
  public Int32 Value { get { return _value;} }

  public MyType(Int32 val)
  {
     _value = val;
  }
}

MyType alpha = new MyType(42);

当字段数量增加并且输入很多时,这变得相当复杂。 有没有更有效的方法来做到这一点?

3 个答案:

答案 0 :(得分:5)

我建议编写更少代码的唯一方法是使用类似ReSharper的东西为您自动生成代码。如果您从以下内容开始:

public class MyType
{
    private int _value;
}

然后,您可以生成“只读属性”来提供:

public class MyType
{
    private int _value;
    public int Value{get {return _value;}}
}

然后生成构造函数给出:

public class MyType
{
    private int _value;
    public int Value{get {return _value;}}

    public MyType(int value)
    {
        _value = value;
    }
}

生成步骤总共是8次按键。


如果你真的想要一个不可修改的不可变类,我会这样声明:

public sealed class MyType
{
    public int Value{get {return _value;}}
    private readonly int _value;

    public MyType(int value)
    {
        _value = value;
    }
}

这使得类不可导出(意味着子类不能修改其内部状态),并且_value属性仅在构造期间可分配。不幸的是,ReSharper没有为此模式生成代码,因此您仍然需要手动构建(大部分)它。

答案 1 :(得分:4)

您可以使用自动属性和私有设置器简化它,如下所示:

public struct MyType
{  
  public Int32 Value { get; private set; }

  public MyType(Int32 val)
  {
     Value = val;
  }
}

答案 2 :(得分:1)

救援时的代码片段! 将此xml保存为“immutable.snippet”,然后转到Visual Studio,选择Tools,Code Snippets Manager并导入它。而已!现在编写“immutable”并按两次TAB,你就拥有了不可变类型。

代码段中的实际代码基于@adrianbanks答案。

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
      <Title>Immutable type (C#)</Title>
      <Author>Alfonso Cora</Author>
      <Description>Creates an immutable type</Description>
      <HelpUrl>http://stackoverflow.com/questions/7236977/how-to-efficiently-implement-immutable-types</HelpUrl>
      <Shortcut>immutable</Shortcut>
    </Header>
    <Snippet>
      <Declarations>
        <Literal Editable="true">
          <ID>type</ID>
          <ToolTip>The type on which this immutable type is based.</ToolTip>
          <Default>int</Default>
          <Function>
          </Function>
        </Literal>
        <Literal Editable="true">
          <ID>class</ID>
          <ToolTip>The name of the immutable type.</ToolTip>
          <Default>MyImmutableType</Default>
          <Function>
          </Function>
        </Literal>
      </Declarations>
      <Code Language="csharp"><![CDATA[public sealed class $class$
{
    public $type$ Value{get {return _value;}}
    private readonly $type$ _value;

    public $class$($type$ value)
    {
        _value = value;
    }
}]]></Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>