Do值类型扩展方法提供对原始值的写访问权限

本文关键字:原始 权限 写访问 类型 扩展 方法 Do | 更新日期: 2023-09-27 18:24:15

我正在为一些自定义的小容量编码和解码算法编写值类型(如int)的扩展方法
可能还有其他设计不使用扩展方法,但我担心这不是我最后一次面临这个问题,所以我想知道扩展方法如何与这种类型的设计配合使用。

例如:

int i = 10;
string str = i.Encode(); // Convert 10 to an unpredictable string such as "tZh0Ao"
i = 5; // Overwrite i with a new value.
i.Decode(str); // Decrypt the string to reassign the original value of 10

我不确定this参数如何用于值类型扩展方法
它只是原始价值的复制品吗
还是像refout参数一样工作,保留对参数值所做的更改?

例如:

/* This method will decode a string,
   and assign the decoded value to 'this' int. */
public static void Decode(this int value, string str)
{
    int result;
    /* ... perform work with str to produce decoded value ... */
    value = result; // Assign the decoded value to 'this' int.
    /* If 'value' is just a copy of the original int,
       the assignment won't have any permanent effect. */
}

Do值类型扩展方法提供对原始值的写访问权限

我想知道扩展方法如何与这种类型的设计配合使用。

他们不是。

C#3.0中引入了扩展方法,以便LINQ能够为任何IEnumerable<T>IQueryable<T>实例找到.Select和其他方法,而不需要这些接口的每个实现都重新定义方法,也不需要破坏已经实现IEnumerable<T>的大量现有代码。

允许此操作不需要允许this ref扩展方法。这并不意味着这样的扩展方法没有意义,也不意味着它们不会有用,只是在创建扩展方法时没有考虑它们。

这和我们没有扩展属性的原因是一样的。允许扩展属性被认为是WPF附加属性IIRC的一部分,但尽管它们可能有意义,但最终证明它们对于预期目标是不必要的,因此被排除在C#语言之外。

如果this ref扩展方法有令人信服的理由,请向语言设计者提出。这就是添加任何新语言功能的方式。如果还不知道令人信服的原因,那么修改编译器所需的额外工作通常是不修改语言的原因。

它只是原始价值的复制品吗?

是的。编译器将所有扩展方法调用转换为等效的静态方法调用。CCD_ 11和CCD_。如果后者不能修改i(因为它没有声明为ref),那么前者也不能。

在.NET Framework中也找不到太多变化的实例方法。通常认为,最好让实例方法返回一个新值,并让调用者担心是将其分配给现有实例还是新实例。假设DateTime.AddDays修改了它被调用的实例(可以这样设计类型)。然后,典型的程序员不会理解为什么

public void AddOneDay(DateTime[] array) {
  for (int i = 0; i < array.Length; i++)
    array[i].AddDays(1);
}

public void AddOneDay(List<DateTime> list) {
  for (int i = 0; i < list.Count; i++)
    list[i].AddDays(1);
}

有着截然不同的行为。

同样的逻辑也适用于您自己的实例方法:尽管该语言确实允许您为自定义值类型创建可变方法,但通常最好避免它们,以防止用户混淆。

如果你的情况是一个例外,如果在你的情况下,改变方法可以带来更好的开发体验,那么向语言开发人员介绍你的情况。

但我认为,如果i.Decode(str)有效,一般用户不会理解它会做什么。更典型的设计是创建

public static int Decode(this string str)

扩展方法,并将其用作

i = str.Decode();

完全避免了这个问题。