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

时间:2013-01-25 17:49:46

标签: c# .net

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

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

.NET框架中是否存在ref关键字的这种用法?

5 个答案:

答案 0 :(得分:7)

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

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

答案 1 :(得分:5)

这用于各种地方。例如,出于性能原因,XNA会在Matrix.Add等方法中大量使用ref。许多Interlocked methods依靠ref进行正常操作。

话虽如此,根据类库的设计指南,ref应该谨慎使用,这部分原因并不常见。甚至还有一个code analysis warning (CA1045)表示不使用ref,但有理由偶尔压制这个。

答案 2 :(得分:5)

您可以使用反射(和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参数的实际表示方式。

答案 3 :(得分:1)

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

它会丢弃ObsoleteCOM相关的方法(因为它们的性质而有很多ref params)。

以下是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();
}

答案 4 :(得分:-2)

DateTime dte;
if (DateTime.TryParse("date text", out dte))
{
    // Parse succeeded dte has the value
}