C# 7.0的“析构函数”

21

我正在阅读关于C# 7.0新功能,至少从给出的示例中,我无法理解“析构函数”将用于什么。

它只是语法糖吗?

如果有人能够对此进行解释,那就太好了。


2
它有什么不清楚的地方吗?至于它是否是语法糖:你所链接的页面已经很明确了:“显然,你可以像在C# 1.0中那样调用Deconstruct方法。然而,C# 7.0提供了语法糖来极大地简化调用。” - Erwin Bolwidt
1
不用担心,这基本上是自动的。一旦您开始使用新的元组语法,您很快就会发现需要使用到这种简化语法。 - Hans Passant
2
似乎C#正在添加新的语法,只是为了与其他语言保持功能平衡,但这并没有增加明确的意图,也没有提供可靠的价值。 - Ryan Russon
这是一种语法糖,我认为我们不需要它... 这让代码更难阅读和理解,只是为了使其更简洁... - ScottishTapWater
2个回答

34

这是新元组语法的一部分——与Tuple<>类无关,而是来自函数式编程。

考虑以下类:

public class User
{
   public string Username { get; }
   public string FirstName { get; }
   public string LastName { get; }

   public User(string username, string firstName, string lastName)
   {
       // initialize properties
   }

   public void Deconstruct(out string username, out string firstName, out string lastName)
   {
       // initialize out parameters
   }
}

使用方法:

var user = new User("foobaa", "foo", "baa");

不要使用

var username = user.Username;
var firstName = user.FirstName;
var lastName = user.LastName;

或者

string username, firstName, lastName;
user.Deconstruct(out username, out firstName, out lastName);

您可以编写:

var (username, firstName, lastName) = user;

var fullName = $"{firstName} {lastName}";

更新


此外,还有一个可能会用到它的例子(这只是猜测,我没有尝试过),就是与模式匹配搭配使用。

var users = new Dictionary<string, User>
{
    {"john", new User("jom", "John", "Malkovich") }
}

C# 6

User user;
users.TryGetValue("john", out user);
C# 7 模式匹配
users.TryGetValue("john", out User user);

C# 7 解构

users.TryGetValue("john", out (username, firstname, lastname));    

那么你的意思就是这只是语法糖?我猜,如果这个特性已经被引入到语言中,那肯定是为了满足某种特定需求。如果我理解正确的话,这个需求是为了一次访问对象实例的多个属性? - David Brabant
可能与旧的“Tuple”类型有关。根据此问题的结果,Tuple可能会有Deconstruct,因此您将能够编写var (x, y) = Tuple.Create(10, 20); - svick
2
我也刚刚了解到这个,对其价值有些不确定。我不怀疑可能存在我没有看到的价值,但希望能看到更好的例子。我看到的例子已经将对象的公共属性分解了,而实际上那些感兴趣的值应该是公共属性。我不认为增加一行代码来声明和提取局部变量而不是简单地使用对象的公共属性,具有价值,甚至可以称之为“语法糖”。 - reads0520
1
这对于需要多个返回值的东西非常有用。例如,我正在开发一个数据包装程序,在其中可以获取byte[]和长度值,而无需将其缓冲到新数据集中以使byte[]的长度值有用,现在我只需获知数组中多少个字节是结果即可。var(buffer,length)= Packer.GetBytes() ..没有令人讨厌的out变量。 - James

-1
如果我的记忆没有出错,这也与 ValueTuple<...> 以及临时元组有关,它们经常会被解构,并且很多时候都是字面上的解构。也就是说,
var tuple = (1, true, "string"); // to bind them all
var (one, flag, s) = tuple;

或者,如果我们将其规范化为一个适当的类:

class Data
{
  public int Value { get; set; }

  public bool Flag { get; set; }

  public string Text { get; set; }

  public void Deconstruct(out int value, out bool flag, out string text) =>
    (value, flag, text) = (this.Value, this.Flag, this.Text);
}

从我有限的经验来看,临时元组是有帮助的,并且在一定程度上有其用途。然后就存在一个界限,需要使用更正式的类定义,支持一个或几个解构用例。

等等。

希望对你有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接