Подделать строковую ссылку - PullRequest
       8

Подделать строковую ссылку

2 голосов
/ 17 сентября 2011

Возможно ли, чтобы вызывающий следующий метод обработал строковую ссылку и передал ее как token, так что метод возвращает true? (Предполагая, что вызывающая сторона не получает ссылку на строку из статического поля, используя отражение.)

class GuessTheSecret
{
    private static readonly string Secret = new string("Secret".ToCharArray());

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

Ответы [ 2 ]

2 голосов
/ 17 сентября 2011

Нет.Вы должны были бы выставить статический экземпляр вызывающей стороне.Ссылочное равенство означает, что это точно такой же объект.Если нет способа получить доступ к этому конкретному объекту, у вас не может быть другого, который ссылается на ту же память.Если бы вы использовали оператор равенства, это было бы иначе, так как 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

0 голосов
/ 17 сентября 2011

Я полагаю, что это "зависит", в основном от того, передает ли вызывающая сторона строку той же сборки, которая была интернирована с вашей строкой.

И вот почему:

ReferenceEquals делает то, что вы думаете, сравнивая области памяти, а не значение объекта ( MSDN ):

Вызвав метод ReferenceEquals, вы можете увидеть, что два Строки фактически ссылаются на один и тот же объект в памяти.

Есть функция C #, называемая интернирование строк , которая, согласно Эрику Липперту:

Если у вас есть два одинаковых строковых литерала в одном модуле компиляции, то сгенерированный нами код гарантирует, что CLR создает только один строковый объект для всех экземпляров этого литерала в сборке. Эта оптимизация называется «интернирование строк».

Однако из того же поста интернирование по умолчанию не гарантируется для каждой строки:

Если вы писали компилятор на C # или у вас было какое-то другое приложение, в котором вы считали, что стоит того, чтобы тысячи одинаковых строк не занимали много памяти, вы можете заставить среду выполнения интернировать вашу строку с методом String.Intern.

И наоборот, если вы ненавидите интернирование с безрассудной страстью, вы можете заставить среду выполнения отключить интернирование всех строк в сборке с атрибутом CompilationRelaxation.

Чего бы вы ни пытались достичь, эта текущая реализация в лучшем случае выглядит ненадежной - я бы подумал переосмыслить то, что вы делаете.

...