Jak*_*ade 22 c# vb.net extension-methods byref
是否真的无法在C#中创建扩展方法,其中实例作为引用传递?
这是一个示例VB.NET控制台应用程序:
Imports System.Runtime.CompilerServices
Module Module1
Sub Main()
Dim workDays As Weekdays
workDays.Add(Weekdays.Monday)
workDays.Add(Weekdays.Tuesday)
Console.WriteLine("Tuesday is a workday: {0}", _
CBool(workDays And Weekdays.Tuesday))
Console.ReadKey()
End Sub
End Module
<Flags()> _
Public Enum Weekdays
Monday = 1
Tuesday = 2
Wednesday = 4
Thursday = 8
Friday = 16
Saturday = 32
Sunday = 64
End Enum
Module Ext
<Extension()> _
Public Sub Add(ByRef Value As Weekdays, ByVal Arg1 As Weekdays)
Value = Value + Arg1
End Sub
End Module
Run Code Online (Sandbox Code Playgroud)
请注意,Value参数是ByRef传递的.
和(几乎)在C#中相同:
using System;
namespace CS.Temp
{
class Program
{
public static void Main()
{
Weekdays workDays = 0;
workDays.Add(Weekdays.Monday); // This won't work
workDays.Add(Weekdays.Tuesday);
// You have to use this syntax instead...
// workDays = workDays | Weekdays.Monday;
// workDays = workDays | Weekdays.Tuesday;
Console.WriteLine("Tuesday is a workday: {0}", _
System.Convert.ToBoolean(workDays & Weekdays.Tuesday));
Console.ReadKey();
}
}
[Flags()]
public enum Weekdays : int
{
Monday = 1,
Tuesday = 2,
Wednesday = 4,
Thursday = 8,
Friday = 16,
Saturday = 32,
Sunday = 64
}
public static class Ext
{
// Value cannot be passed by reference?
public static void Add(this Weekdays Value, Weekdays Arg1)
{
Value = Value | Arg1;
}
}
}
Run Code Online (Sandbox Code Playgroud)
该Add扩展方法没有在C#中工作,因为我不能使用ref关键字.这有什么解决方法吗?
Gis*_*shu 13
不可以.在C#中,ref除了this扩展方法的第一个参数之外,你不能指定任何修饰符(比如'out'或者)- 你可以为其他修饰符指定.不熟悉VB语法,但它似乎使用声明方法来标记扩展方法.
调用它时,不指定第一个this参数.因此将参数标记为out或ref没有意义,因为您在调用它时无法像通常的方法那样指定修饰符
void MyInstanceMethod(ref SomeClass c, int data) { ... } // definition
obj.MyInstanceMethod(ref someClassObj, 10); // call
void MyExtensionMethod(this SomeClass c, int data) {.... } // defn
c.MyExtensionMethod(10); // call
Run Code Online (Sandbox Code Playgroud)
我认为你在这里遇到的麻烦与价值类型是不可变的有关.如果工作日是一个参考类型,它会好起来的.对于不可变类型(结构),事实上的方法是返回具有所需值的新实例.例如,请参阅结构DateTime上的Add方法,它返回一个新的DateTime实例,其值= receiver DateTime实例的值+ param值.
public DateTime Add( TimeSpan value )
Run Code Online (Sandbox Code Playgroud)
Sam*_*ell 11
Yikes - 你正在制作一个可变的不可变结构.它打破了人们期望在C#中看到的内容,但如果必须,那么您可以随时直接调用该方法:
Ext.Add(ref value, arg1);
Run Code Online (Sandbox Code Playgroud)
任何扩展方法都可以直接调用.
另外,澄清一下:
SomeReferenceType value = ...;
SomeReferenceType copy = value;
value.ExtensionMethodByRef(...);
// this failing is semantically ridiculous for reference types, which
// is why it makes no sense to pass a `this` parameter by ref.
object.ReferenceEquals(value, copy);
Run Code Online (Sandbox Code Playgroud)
奇怪的是 VB.NET 允许这样做而 C# 不允许......
然而,虽然从技术角度来看可能有意义(因为扩展方法只是一个静态方法),但我认为它感觉不对,因为扩展方法被当作实例方法使用,并且实例方法可以'不修改this引用。