C# 为什么WPF表示库在StringBuilder.ToString()中包装字符串?

C# 为什么WPF表示库在StringBuilder.ToString()中包装字符串?,c#,.net,wpf,string,stringbuilder,C#,.net,Wpf,String,Stringbuilder,ILSpy在PresentationCore.dll(.NET4 WPF)中找到的代码: uri.GetComponents的返回类型是string,为什么该方法不直接返回string值,而不是将其包装在StringBuilder(string).ToString()中这是设计的吗?一般来说,这样做的原因是什么?它会减少分配、改进垃圾收集还是用于线程安全?我唯一能想到的是,如果传入stringBuilder的第一个参数为null,则stringBuilder将返回string.empty而不是n

ILSpy在
PresentationCore.dll
(.NET4 WPF)中找到的代码:


uri.GetComponents
的返回类型是
string
,为什么该方法不直接返回
string
值,而不是将其包装在
StringBuilder(string).ToString()中这是设计的吗?一般来说,这样做的原因是什么?它会减少分配、改进垃圾收集还是用于线程安全?

我唯一能想到的是,如果传入stringBuilder的第一个参数为null,则stringBuilder将返回string.empty而不是null(请参阅)

但是字符串可以为空。。。那为什么要麻烦

与新建stringBuilder实例相比,只需执行一次检查并返回一个空字符串,效率会高很多

第二个参数只是stringbuilder应初始化为的建议大小

关于OP问题的评论是正确的,似乎有些过激。

//
/// <SecurityNote> 
/// Critical: Calls the native InternetGetCookieEx(). There is potential for information disclosure. 
/// Safe: A WebPermission demand is made for the given URI.
/// </SecurityNote> 
[SecurityCritical, SecurityTreatAsSafe]
[FriendAccessAllowed] // called by PF.Application.GetCookie()
[SuppressMessage("Microsoft.Interoperability", "CA1404:CallGetLastErrorImmediatelyAfterPInvoke",
    Justification="It's okay now. Be careful on change.")] 
internal static string GetCookie(Uri uri, bool throwIfNoCookie)
{ 
    // Always demand in order to prevent any cross-domain information leak. 
    SecurityHelper.DemandWebPermission(uri);

    UInt32 size = 0;
    string uriString = BindUriHelper.UriToString(uri);
    if (UnsafeNativeMethods.InternetGetCookieEx(uriString, null, null, ref size, 0, IntPtr.Zero))
    { 
        Debug.Assert(size > 0);
        size++; 
        System.Text.StringBuilder sb = new System.Text.StringBuilder((int)size); 
        // PresentationHost intercepts InternetGetCookieEx(). It will set the INTERNET_COOKIE_THIRD_PARTY
        // flag if necessary. 
        if (UnsafeNativeMethods.InternetGetCookieEx(uriString, null, sb, ref size, 0, IntPtr.Zero))
        {
            return sb.ToString();
        } 
    }
    if (!throwIfNoCookie && Marshal.GetLastWin32Error() == NativeMethods.ERROR_NO_MORE_ITEMS) 
        return null; 
    throw new Win32Exception(/*uses last error code*/);
}

/// <SecurityNote> 
/// Critical: Sets cookies via the native InternetSetCookieEx(); doesn't demand WebPermission for the given 
///     URI. This creates danger of overwriting someone else's cookies.
///     The P3P header has to be from an authentic web response in order to be trusted at all. 
/// </SecurityNote>
[SecurityCritical]
private static bool SetCookieUnsafe(Uri uri, string cookieData, string p3pHeader)
{ 
    string uriString = BindUriHelper.UriToString(uri);
    // PresentationHost intercepts InternetSetCookieEx(). It will set the INTERNET_COOKIE_THIRD_PARTY 
    // flag if necessary. (This doesn't look very elegant but is much simpler than having to make the 
    // 3rd party decision here as well or calling into the native code (from PresentationCore).)
    uint res = UnsafeNativeMethods.InternetSetCookieEx( 
        uriString, null, cookieData, UnsafeNativeMethods.INTERNET_COOKIE_EVALUATE_P3P, p3pHeader);
    if(res == 0)
        throw new Win32Exception(/*uses last error code*/);
    return res != UnsafeNativeMethods.COOKIE_STATE_REJECT; 
}

    private const int MAX_PATH_LENGTH = 2048 ; 
    private const int MAX_SCHEME_LENGTH = 32;
    public const int MAX_URL_LENGTH = MAX_PATH_LENGTH + MAX_SCHEME_LENGTH + 3; /*=sizeof("://")*/ 

    //
    // Uri-toString does 3 things over the standard .toString()
    // 
    //  1) We don't unescape special control characters. The default Uri.ToString()
    //     will unescape a character like ctrl-g, or ctrl-h so the actual char is emitted. 
    //     However it's considered safer to emit the escaped version. 
    //
    //  2) We truncate urls so that they are always <= MAX_URL_LENGTH 
    //
    // This method should be called whenever you are taking a Uri
    // and performing a p-invoke on it.
    // 
    internal static string UriToString(Uri uri)
    { 
        if (uri == null) 
        {
            throw new ArgumentNullException("uri"); 
        }

        return new StringBuilder(
            uri.GetComponents( 
                uri.IsAbsoluteUri ? UriComponents.AbsoluteUri : UriComponents.SerializationInfoString,
                UriFormat.SafeUnescaped), 
            MAX_URL_LENGTH).ToString(); 
    }
///关键:调用本机InternetGetCookieEx()。存在信息披露的可能性。 ///安全:对给定URI发出WebPermission请求。 /// [SecurityCritical,SecurityTreatAsSafe] [FriendAccessAllowed]//由PF.Application.GetCookie()调用 [SuppressMessage(“Microsoft.Interoperability”,“CA1404:CallGetLastErrorImmediatelyAfterPInvoke”, justion=“现在没事了,换衣服要小心。”)] 内部静态字符串GetCookie(Uri、bool throwifnocokie) { //始终请求以防止任何跨域信息泄漏。 SecurityHelper.DemandWebPermission(uri); UInt32尺寸=0; 字符串uriString=BindUriHelper.UriToString(uri); if(unsafentiveMethods.InternetGetCookieEx(uriString,null,null,ref size,0,IntPtr.Zero)) { 断言(大小>0); 大小++; System.Text.StringBuilder sb=新的System.Text.StringBuilder((int)大小); //PresentationHost拦截InternetGetCookieEx()。它将设置INTERNET\u COOKIE\u第三方 //如有必要,标记。 if(unsafentiveMethods.InternetGetCookieEx(uriString,null,sb,ref size,0,IntPtr.Zero)) { 使某人返回字符串(); } } 如果(!throwifnocokie&&Marshal.GetLastWin32Error()==NativeMethods.ERROR\u无\u更多\u项) 返回null; 抛出新的Win32Exception(/*使用最后一个错误代码*/); } /// ///关键:通过本机InternetSetCookieEx()设置cookie;不要求对给定的 ///乌里。这会造成覆盖其他人的cookie的危险。 ///P3P头必须来自真实的web响应,才能被信任。 /// [证券评论] 私有静态bool SetCookieUnsafe(Uri、字符串cookieData、字符串p3pHeader) { 字符串uriString=BindUriHelper.UriToString(uri); //PresentationHost拦截InternetSetCookieEx()。它将设置INTERNET\u COOKIE\u第三方 //如果必要的话,可以挂上旗子。(这看起来不是很优雅,但比制作 //第三方也可在此作出决定或调用本机代码(来自PresentationCore)。) uint res=非预防性方法。InternetSetCookieEx( uriString、null、cookieData、unsafentiveMethods.INTERNET\u COOKIE\u EVALUATE\u P3P、p3pHeader); 如果(res==0) 抛出新的Win32Exception(/*使用最后一个错误代码*/); return res!=unsafentivemethods.COOKIE\u STATE\u REJECT; } 私有常量int MAX_PATH_LENGTH=2048; 私有const int MAX_SCHEME_LENGTH=32; public const int MAX_URL_LENGTH=MAX_PATH_LENGTH+MAX_SCHEME_LENGTH+3/*=大小(“:/”)*/ // //Uri toString比标准做了3件事 // //1)我们不取消特殊控制字符的显示。默认的Uri.ToString() //将取消对ctrl-g或ctrl-h这样的字符的切换,以便发出实际的字符。 //但是,发出转义版本被认为更安全。 //
//2)我们截断URL,使其始终保持不变,这毫无意义。(顺便说一句,2083是Internet Explorer支持的最大URL长度。但知道这一点,它仍然没有意义。)@HamletHakobyan为什么人们不“相信”反编译器?反编译器以说谎而闻名吗?@HamletHakobyan如果反编译器说正在调用StringBuilder,那么正在调用StringBuilder。无需转到框架源代码。祝贺您,OP。。您问了一个问题,唯一的答案是开发人员在实现该功能的那天喝醉了。我想不出为什么要这样做。甚至连“线程安全”都没有。。考虑到字符串本质上是线程安全的(除非在该程序集中的某个地方发生了一些不安全的事情)。@SimonWhitehead我不是在讨论标识符无效的情况,这些标识符仍然显示与实际行为相匹配的易读代码,而是反编译代码有细微错误的情况,例如,因为它选择了不同的重载(如我前面的示例中所示),或者反编译器弄乱了控制流。当然,现在您可以只执行
返回uri.GetComponents(uri.IsAbsoluteUri?UriComponents.AbsoluteUri:UriComponents.SerializationInfoString,UriFormat.SafeUnescaped)??"";Uri.GetComponents()
可以返回null…我不明白<代码>我们截断URL,使其始终保持不变。很明显,这是一个Microsoft不知道的错误,或者认为不需要修复。
/// <SecurityNote> 
/// Critical: Calls the native InternetGetCookieEx(). There is potential for information disclosure. 
/// Safe: A WebPermission demand is made for the given URI.
/// </SecurityNote> 
[SecurityCritical, SecurityTreatAsSafe]
[FriendAccessAllowed] // called by PF.Application.GetCookie()
[SuppressMessage("Microsoft.Interoperability", "CA1404:CallGetLastErrorImmediatelyAfterPInvoke",
    Justification="It's okay now. Be careful on change.")] 
internal static string GetCookie(Uri uri, bool throwIfNoCookie)
{ 
    // Always demand in order to prevent any cross-domain information leak. 
    SecurityHelper.DemandWebPermission(uri);

    UInt32 size = 0;
    string uriString = BindUriHelper.UriToString(uri);
    if (UnsafeNativeMethods.InternetGetCookieEx(uriString, null, null, ref size, 0, IntPtr.Zero))
    { 
        Debug.Assert(size > 0);
        size++; 
        System.Text.StringBuilder sb = new System.Text.StringBuilder((int)size); 
        // PresentationHost intercepts InternetGetCookieEx(). It will set the INTERNET_COOKIE_THIRD_PARTY
        // flag if necessary. 
        if (UnsafeNativeMethods.InternetGetCookieEx(uriString, null, sb, ref size, 0, IntPtr.Zero))
        {
            return sb.ToString();
        } 
    }
    if (!throwIfNoCookie && Marshal.GetLastWin32Error() == NativeMethods.ERROR_NO_MORE_ITEMS) 
        return null; 
    throw new Win32Exception(/*uses last error code*/);
}

/// <SecurityNote> 
/// Critical: Sets cookies via the native InternetSetCookieEx(); doesn't demand WebPermission for the given 
///     URI. This creates danger of overwriting someone else's cookies.
///     The P3P header has to be from an authentic web response in order to be trusted at all. 
/// </SecurityNote>
[SecurityCritical]
private static bool SetCookieUnsafe(Uri uri, string cookieData, string p3pHeader)
{ 
    string uriString = BindUriHelper.UriToString(uri);
    // PresentationHost intercepts InternetSetCookieEx(). It will set the INTERNET_COOKIE_THIRD_PARTY 
    // flag if necessary. (This doesn't look very elegant but is much simpler than having to make the 
    // 3rd party decision here as well or calling into the native code (from PresentationCore).)
    uint res = UnsafeNativeMethods.InternetSetCookieEx( 
        uriString, null, cookieData, UnsafeNativeMethods.INTERNET_COOKIE_EVALUATE_P3P, p3pHeader);
    if(res == 0)
        throw new Win32Exception(/*uses last error code*/);
    return res != UnsafeNativeMethods.COOKIE_STATE_REJECT; 
}

    private const int MAX_PATH_LENGTH = 2048 ; 
    private const int MAX_SCHEME_LENGTH = 32;
    public const int MAX_URL_LENGTH = MAX_PATH_LENGTH + MAX_SCHEME_LENGTH + 3; /*=sizeof("://")*/ 

    //
    // Uri-toString does 3 things over the standard .toString()
    // 
    //  1) We don't unescape special control characters. The default Uri.ToString()
    //     will unescape a character like ctrl-g, or ctrl-h so the actual char is emitted. 
    //     However it's considered safer to emit the escaped version. 
    //
    //  2) We truncate urls so that they are always <= MAX_URL_LENGTH 
    //
    // This method should be called whenever you are taking a Uri
    // and performing a p-invoke on it.
    // 
    internal static string UriToString(Uri uri)
    { 
        if (uri == null) 
        {
            throw new ArgumentNullException("uri"); 
        }

        return new StringBuilder(
            uri.GetComponents( 
                uri.IsAbsoluteUri ? UriComponents.AbsoluteUri : UriComponents.SerializationInfoString,
                UriFormat.SafeUnescaped), 
            MAX_URL_LENGTH).ToString(); 
    }