Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 伪造字符串引用_C#_.net_String - Fatal编程技术网

C# 伪造字符串引用

C# 伪造字符串引用,c#,.net,string,C#,.net,String,以下方法的调用者是否可以手工创建一个字符串引用,并将其作为token传递,以便该方法返回true?(假设调用方没有使用反射从静态字段获取字符串引用。) 不,您必须向调用方公开静态实例。引用相等意味着它是完全相同的对象。除非有办法访问特定对象,否则不能有另一个引用相同内存的对象。如果要使用相等运算符,则会有所不同,因为string重载了值相等而不是引用相等 另一方面,如果您将静态实例值设置为常量,那么(通过使用该常量)可以有一个等于静态实例的引用。这是因为字符串文本在整个代码中都是内部的和共享的,

以下方法的调用者是否可以手工创建一个字符串引用,并将其作为
token
传递,以便该方法返回true?(假设调用方没有使用反射从静态字段获取字符串引用。)


不,您必须向调用方公开静态实例。引用相等意味着它是完全相同的对象。除非有办法访问特定对象,否则不能有另一个引用相同内存的对象。如果要使用相等运算符,则会有所不同,因为
string
重载了值相等而不是引用相等

另一方面,如果您将静态实例值设置为常量,那么(通过使用该常量)可以有一个等于静态实例的引用。这是因为字符串文本在整个代码中都是内部的和共享的,这意味着所有相同的字符串文本都具有相同的引用

比如说,

class GuessTheSecret
{
    private static readonly string Secret = "Secret";

    public static bool IsCorrect(string token)
    {
        return object.ReferenceEquals(token, Secret);
    }
}

Console.WriteLine( GuessTheSecret.IsCorrect( "Secret" ) );
将输出
True

我认为是“它取决于”,基本上取决于调用者是否传递与您的字符串相同的程序集字符串

原因如下:

ReferenceEquals按照您的想法,比较内存位置而不是对象值():

通过调用ReferenceEquals方法,您可以看到 字符串实际上是指内存中的同一对象

根据Eric Lippert的说法,有一个C#特性叫做:

如果在一个编译单元中有两个相同的字符串文本,那么我们生成的代码将确保CLR仅为程序集中该文本的所有实例创建一个字符串对象。这种优化称为“字符串实习”

但是,在同一篇文章中,默认情况下不保证每个字符串都有实习:

如果您正在用C#编写编译器,或者在其他应用程序中,您觉得有必要确保数千个相同的字符串不会占用大量内存,那么可以强制运行时使用string.intern方法对字符串进行内部存储

相反,如果您不喜欢以一种非理性的热情进行内部调用,则可以强制运行时关闭具有compliationrelaxation属性的程序集中的所有字符串内部调用


不管你想完成什么,当前的实现你似乎是最不可靠的——我会考虑重新思考你正在做的事情。< / P> BAH,错过你的免责声明;如果某个未来版本的编译器/抖动成功地将初始值设定项优化为常数,那么这很容易实现。或者如果它只是在初始化静态变量后决定对其进行内部调用。否则我就没办法了。@CodeInChaos只读到常量优化是不可能的。该代码容易受到简单的暴力攻击。不应该超过几毫秒。@Hans:我并不真正关心复杂的攻击(使用反射更容易),但我很好奇:如何在.NET中制作引用和测试,如果其中一个恰好是您要查找的引用?如果CLR决定出于某种原因来实作我的秘密字符串呢?@ DTB-我会认为如果您明确地使用<代码>新< /代码>,这将是一个错误。在这种情况下,你,程序员,正在要求一个新的参考。在这种情况下,编译器编写者不应该试图超越程序员。在

新字符串('a',0)
的情况下,CLR的作用就是:它返回对内部字符串的引用
,而不是创建一个长度为零的新字符串对象并返回对它的引用。@dtb-阅读Jon Skeet对它的评论,我假设,如果你想实习文字以外的任何东西,你必须要求实习:@dtb:空字符串似乎是文档中的一个特例。用非空字符串进行实验,比如你的秘密字符串,看看有没有什么奇怪的地方。同一个MSDN页面上说,只会自动对文字进行实习,否则,
string.Intern()
会根据需要进行实习。因此文字“秘密”被实习。如果我愿意,我可以实习
新字符串(“Secret.tocharray())
。我可以禁用在整个程序集范围内进行实习。到目前为止,一切顺利。剩下的问题是:
newstring(“Secret.tocharray())
是否会因为某种原因自动被拘留,以致
Secret
字段引用了被拘留的字符串?考虑到是谁在问这个问题,我认为这只是出于教育目的,而不是为了生产代码
class GuessTheSecret
{
    private static readonly string Secret = "Secret";

    public static bool IsCorrect(string token)
    {
        return object.ReferenceEquals(token, Secret);
    }
}

Console.WriteLine( GuessTheSecret.IsCorrect( "Secret" ) );