.NET 框架库中的 ref 关键字示例

本文关键字:关键字 ref 框架 NET | 更新日期: 2023-09-27 17:56:07

DateTime.TryParse方法都有一个DateTime out参数。

public static bool TryParse(string s, out DateTime result)

在.NET framework中是否有ref关键字的此类用法?

.NET 框架库中的 ref 关键字示例

是的

,例如Interlocked.Exchange的各种重载:

public static double Exchange(
ref double location1,
double value
)

这在不同位置使用。 例如,出于性能原因,XNA在Matrix.Add等方法中大量使用ref。 许多联锁方法依靠ref进行正确操作。

话虽如此,根据类库的设计指南,ref是应该谨慎使用的东西,这也是它不是很常见的部分原因。 甚至还有一个代码分析警告(CA1045)建议不要使用ref,尽管有理由偶尔抑制它。

您可以使用反射(和 LINQ)获取 mscorlib 中所有ref方法的列表:

from type in typeof(object).Assembly.GetExportedTypes()
where !type.IsInterface
from method in type.GetMethods()
where method.GetParameters().Any(
    p => p.ParameterType.IsByRef &&
        !p.GetCustomAttributes(typeof(OutAttribute), false).Any())
select method

过滤掉具有ref参数和OutAttribute的方法是必要的,因为这就是参数的实际表示方式out

实际上,我自己也很好奇,所以我写了一个小程序来扫描.NET Framework程序集,并转储出至少有一个ref参数的公共方法。它使用单色塞西尔静态反射功能。

它丢弃了ObsoleteCOM相关的方法(由于其性质,它们有很多引用参数)。

以下是mscorlib,system和system.core的结果:

Assembly mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
 Type SafeHandle
  Method System.Void DangerousAddRef(System.Boolean& success)
 Type Interlocked
  Method System.Int32 Increment(System.Int32& location)
  Method System.Int64 Increment(System.Int64& location)
  Method System.Int32 Decrement(System.Int32& location)
  Method System.Int64 Decrement(System.Int64& location)
  Method System.Int32 Exchange(System.Int32& location1, System.Int32 value)
  Method System.Int64 Exchange(System.Int64& location1, System.Int64 value)
  Method System.Single Exchange(System.Single& location1, System.Single value)
  Method System.Double Exchange(System.Double& location1, System.Double value)
  Method System.Object Exchange(System.Object& location1, System.Object value)
  Method System.IntPtr Exchange(System.IntPtr& location1, System.IntPtr value)
  Method T Exchange(T& location1, T value)
  Method System.Int32 CompareExchange(System.Int32& location1, System.Int32 value, System.Int32 comparand)
  Method System.Int64 CompareExchange(System.Int64& location1, System.Int64 value, System.Int64 comparand)
  Method System.Single CompareExchange(System.Single& location1, System.Single value, System.Single comparand)
  Method System.Double CompareExchange(System.Double& location1, System.Double value, System.Double comparand)
  Method System.Object CompareExchange(System.Object& location1, System.Object value, System.Object comparand)
  Method System.IntPtr CompareExchange(System.IntPtr& location1, System.IntPtr value, System.IntPtr comparand)
  Method T CompareExchange(T& location1, T value, T comparand)
  Method System.Int32 Add(System.Int32& location1, System.Int32 value)
  Method System.Int64 Add(System.Int64& location1, System.Int64 value)
  Method System.Int64 Read(System.Int64& location)
 Type Volatile
  Method System.Boolean Read(System.Boolean& location)
  Method System.SByte Read(System.SByte& location)
  Method System.Byte Read(System.Byte& location)
  Method System.Int16 Read(System.Int16& location)
  Method System.UInt16 Read(System.UInt16& location)
  Method System.Int32 Read(System.Int32& location)
  Method System.UInt32 Read(System.UInt32& location)
  Method System.Int64 Read(System.Int64& location)
  Method System.UInt64 Read(System.UInt64& location)
  Method System.IntPtr Read(System.IntPtr& location)
  Method System.UIntPtr Read(System.UIntPtr& location)
  Method System.Single Read(System.Single& location)
  Method System.Double Read(System.Double& location)
  Method T Read(T& location)
  Method System.Void Write(System.Boolean& location, System.Boolean value)
  Method System.Void Write(System.SByte& location, System.SByte value)
  Method System.Void Write(System.Byte& location, System.Byte value)
  Method System.Void Write(System.Int16& location, System.Int16 value)
  Method System.Void Write(System.UInt16& location, System.UInt16 value)
  Method System.Void Write(System.Int32& location, System.Int32 value)
  Method System.Void Write(System.UInt32& location, System.UInt32 value)
  Method System.Void Write(System.Int64& location, System.Int64 value)
  Method System.Void Write(System.UInt64& location, System.UInt64 value)
  Method System.Void Write(System.IntPtr& location, System.IntPtr value)
  Method System.Void Write(System.UIntPtr& location, System.UIntPtr value)
  Method System.Void Write(System.Single& location, System.Single value)
  Method System.Void Write(System.Double& location, System.Double value)
  Method System.Void Write(T& location, T value)
 Type LazyInitializer
  Method T EnsureInitialized(T& target)
  Method T EnsureInitialized(T& target, System.Func`1<T> valueFactory)
  Method T EnsureInitialized(T& target, System.Boolean& initialized, System.Object& syncLock)
  Method T EnsureInitialized(T& target, System.Boolean& initialized, System.Object& syncLock, System.Func`1<T> valueFactory)
 Type SafeBuffer
  Method System.Void AcquirePointer(System.Byte*& pointer)
 Type Marshal
  Method System.Int32 QueryInterface(System.IntPtr pUnk, System.Guid& iid, System.IntPtr& ppv)
  Method System.Reflection.MemberInfo GetMethodInfoForComSlot(System.Type t, System.Int32 slot, System.Runtime.InteropServices.ComMemberType& memberType)
 Type EventRegistrationTokenTable`1
  Method System.Runtime.InteropServices.WindowsRuntime.EventRegistrationTokenTable`1<T> GetOrCreateEventRegistrationTokenTable(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationTokenTable`1<T>& refEventTable)
 Type UnmanagedMemoryAccessor
  Method System.Void Write(System.Int64 position, T& structure)
 Type AsyncVoidMethodBuilder
  Method System.Void Start(TStateMachine& stateMachine)
  Method System.Void AwaitOnCompleted(TAwaiter& awaiter, TStateMachine& stateMachine)
  Method System.Void AwaitUnsafeOnCompleted(TAwaiter& awaiter, TStateMachine& stateMachine)
 Type AsyncTaskMethodBuilder
  Method System.Void Start(TStateMachine& stateMachine)
  Method System.Void AwaitOnCompleted(TAwaiter& awaiter, TStateMachine& stateMachine)
  Method System.Void AwaitUnsafeOnCompleted(TAwaiter& awaiter, TStateMachine& stateMachine)
 Type AsyncTaskMethodBuilder`1
  Method System.Void Start(TStateMachine& stateMachine)
  Method System.Void AwaitOnCompleted(TAwaiter& awaiter, TStateMachine& stateMachine)
  Method System.Void AwaitUnsafeOnCompleted(TAwaiter& awaiter, TStateMachine& stateMachine)
Assembly System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
 Type EventProvider
  Method System.Boolean WriteEvent(System.Diagnostics.Eventing.EventDescriptor& eventDescriptor, System.Object[] eventPayload)
  Method System.Boolean WriteEvent(System.Diagnostics.Eventing.EventDescriptor& eventDescriptor, System.String data)
  Method System.Boolean WriteTransferEvent(System.Diagnostics.Eventing.EventDescriptor& eventDescriptor, System.Guid relatedActivityId, System.Object[] eventPayload)
  Method System.Void SetActivityId(System.Guid& id)
Assembly System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
 Type IIntellisenseBuilder
  Method System.Boolean Show(System.String language, System.String value, System.String& newValue)
 Type Executor
  Method System.Int32 ExecWaitWithCapture(System.String cmd, System.CodeDom.Compiler.TempFileCollection tempFiles, System.String& outputName, System.String& errorName)
  Method System.Int32 ExecWaitWithCapture(System.String cmd, System.String currentDir, System.CodeDom.Compiler.TempFileCollection tempFiles, System.String& outputName, System.String& errorName)
  Method System.Int32 ExecWaitWithCapture(System.IntPtr userToken, System.String cmd, System.CodeDom.Compiler.TempFileCollection tempFiles, System.String& outputName, System.String& errorName)
  Method System.Int32 ExecWaitWithCapture(System.IntPtr userToken, System.String cmd, System.String currentDir, System.CodeDom.Compiler.TempFileCollection tempFiles, System.String& outputName, System.String& errorName)
 Type Uri
  Method System.Char HexUnescape(System.String pattern, System.Int32& index)
 Type Socket
  Method System.Int32 ReceiveMessageFrom(System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags& socketFlags, System.Net.EndPoint& remoteEP, System.Net.Sockets.IPPacketInformation& ipPacketInformation)
  Method System.Int32 ReceiveFrom(System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint& remoteEP)
  Method System.Int32 ReceiveFrom(System.Byte[] buffer, System.Int32 size, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint& remoteEP)
  Method System.Int32 ReceiveFrom(System.Byte[] buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint& remoteEP)
  Method System.Int32 ReceiveFrom(System.Byte[] buffer, System.Net.EndPoint& remoteEP)
  Method System.IAsyncResult BeginReceiveMessageFrom(System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint& remoteEP, System.AsyncCallback callback, System.Object state)
  Method System.Int32 EndReceiveMessageFrom(System.IAsyncResult asyncResult, System.Net.Sockets.SocketFlags& socketFlags, System.Net.EndPoint& endPoint, System.Net.Sockets.IPPacketInformation& ipPacketInformation)
  Method System.IAsyncResult BeginReceiveFrom(System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint& remoteEP, System.AsyncCallback callback, System.Object state)
  Method System.Int32 EndReceiveFrom(System.IAsyncResult asyncResult, System.Net.EndPoint& endPoint)
 Type UdpClient
  Method System.Byte[] Receive(System.Net.IPEndPoint& remoteEP)
  Method System.Byte[] EndReceive(System.IAsyncResult asyncResult, System.Net.IPEndPoint& remoteEP)

这是程序:

static void EnumerateMethodsWithRefParameters()
{
    foreach (FileInfo file in new DirectoryInfo(RuntimeEnvironment.GetRuntimeDirectory()).GetFiles("*.dll"))
    {
        AssemblyDefinition asm;
        try
        {
            asm = AssemblyFactory.GetAssembly(file.FullName);
        }
        catch (ImageFormatException)
        {
            continue;
        }
        bool assemblyWritten = false;
        foreach (ModuleDefinition module in asm.Modules)
        {
            foreach (TypeDefinition type in module.Types)
            {
                if (!ChooseType(type))
                    continue;
                bool typeWritten = false;
                foreach (MethodDefinition method in type.Methods)
                {
                    if (!ChooseMethod(method))
                        continue;
                    if (!assemblyWritten)
                    {
                        Console.WriteLine("Assembly " + asm.Name);
                        assemblyWritten = true;
                    }
                    if (!typeWritten)
                    {
                        Console.WriteLine(" Type " + type.Name);
                        typeWritten = true;
                    }
                    Console.WriteLine("  Method " + GetMethodSignature(method));
                }
            }
        }
    }
}
static bool ChooseType(TypeDefinition type)
{
    if (!type.IsPublic)
        return false;
    if (IsComRelatedOrObsolete(type))
        return false;
    return true;
}
static bool ChooseMethod(MethodDefinition method)
{
    if (!method.IsPublic)
        return false;
    foreach (ParameterDefinition parameter in method.Parameters)
    {
        if ((parameter.ParameterType is ReferenceType) && (!parameter.IsOut))
            return true;
    }
    return false;
}
static bool IsComRelatedOrObsolete(TypeDefinition type)
{
    foreach (CustomAttribute att in type.CustomAttributes)
    {
        if (att.Constructor.DeclaringType.FullName == typeof(ObsoleteAttribute).FullName)
            return true;
        if (att.Constructor.DeclaringType.FullName == typeof(InterfaceTypeAttribute).FullName)
        {
            if ((att.Constructor.Parameters.Count > 0) &&
                (att.Constructor.Parameters[0].ParameterType.FullName == typeof(ComInterfaceType).FullName))
                return true;
        }
        if (att.Constructor.DeclaringType.FullName == typeof(ComVisibleAttribute).FullName)
            return true;
        if (att.Constructor.DeclaringType.FullName == typeof(ComConversionLossAttribute).FullName)
            return true;
        if (att.Constructor.DeclaringType.FullName == typeof(ComImportAttribute).FullName)
            return true;
    }
    return false;
}
static string GetMethodSignature(MethodDefinition method)
{
    StringBuilder sb = new StringBuilder(method.ReturnType.ReturnType.FullName);
    sb.Append(' ');
    sb.Append(method.Name);
    sb.Append("(");
    for (int i = 0; i < method.Parameters.Count; i++)
    {
        ParameterDefinition p = method.Parameters[i];
        sb.Append(p.ParameterType.FullName);
        if (!string.IsNullOrEmpty(p.Name))
        {
            sb.Append(' ');
            sb.Append(p.Name);
        }
        if (i != (method.Parameters.Count - 1))
        {
            sb.Append(", ");
        }
    }
    sb.Append(")");
    return sb.ToString();
}
DateTime dte;
if (DateTime.TryParse("date text", out dte))
{
    // Parse succeeded dte has the value
}