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
参数如何用于值类型扩展方法
它只是原始价值的复制品吗
还是像ref
或out
参数一样工作,保留对参数值所做的更改?
例如:
/* 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. */
}
我想知道扩展方法如何与这种类型的设计配合使用。
他们不是。
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();
完全避免了这个问题。