C# 扩展方法不允许通过引用传递参数吗?
在 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
请注意,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;
}
}
}
Add
扩展方法在 C# 中不起作用,因为我无法使用 ref
关键字。 有什么解决方法吗?
Is it really impossible to create an extension method in C# where the instance is passed as a reference?
Here’s a sample VB.NET console app:
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
Note the Value parameter is passed ByRef.
And (almost) the same in 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;
}
}
}
The Add
extension method doesn’t work in C# because I can’t use the ref
keyword. Is there any workaround for this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
不可以。在 C# 中,您不能为扩展方法的第一个参数指定除
this
之外的任何修饰符(例如“out”或ref
) - 你可以为别人。 不熟悉 VB 语法,但它似乎使用声明性方法来标记扩展方法。当您调用它时,您不指定第一个
this
参数。 因此,将参数标记为 out 或 ref 没有意义,因为您在调用它时无法像普通方法那样指定修饰符,我认为您在这里遇到的麻烦与不可变的值类型有关。 如果 Weekdays 是一个参考类型,那就没问题了。 对于不可变类型(结构),事实上的方法是返回具有所需值的新实例。 例如,参见 struct DateTime 上的 Add 方法,它返回一个新的 DateTime 实例,其值 = 接收者 DateTime 实例的值 + 参数值。
No. In C#, you cannot specify any modifiers (like 'out' or
ref
) other thanthis
for the first parameter of an extension method - you can for the others. Not familiar with the VB Syntax but it seems to be using a declarative approach to mark an extension method.When you call it, you do not specify the first
this
parameter. Hence marking the parameter as out or ref doesnt make sense as You can't specify the modifier when you call it like you'd do for normal methodsI think the trouble you're having here is related to value types being immutable. If Weekdays was a reference type, it would work out alright. For immutable types (structs), the defacto way is to return a new instance with the required value. E.g. See the Add method on the struct DateTime, it returns a new DateTime instance whose value = receiver DateTime instance's value + param value.
哎呀 - 你正在创建一个可变的不可变结构。 它打破了人们期望在 C# 中看到的内容,但如果必须的话,那么您始终可以直接调用该方法:
任何扩展方法都可以直接调用。
另外,澄清一下:
Yikes - you're making a mutable immutable struct. It breaks what people expect to see in C#, but if you must, then you can always directly call the method:
Any extension method is directly callable.
Also, a clarification:
奇怪的是 VB.NET 允许这样做,而 C# 不允许...
但是,虽然从技术角度来看这可能有意义(因为扩展方法只是一个静态方法),但我认为这感觉不对,因为扩展方法的使用就像实例方法一样,并且实例方法不能修改
this
引用。Strange that VB.NET allows this and C# doesn't...
However, although it might make sense from a technical point of view (since an extension method is just a static method), I think it doesn't feel right, because extension methods are used as if they were instance methods, and instance methods can't modify the
this
reference.