GeekBrains вопросы - Входное тестирование. ReferenceEquals С#

Ребята, проходил тестирования входное от GeekBrains. Это для бесплатных курсов по программированию. Я честно сказать обалдел от сложности вопросов. Вот один из них, может кому полезно будет. Я программист C# и то не сразу догадался, какой правильный ответ.

Какой результат сравнения будет выведен на экран в указанных трёх строках?

public class Text
{
    public string Value1 { get; } = new string("Hello");
    public string Value2 => new string("Hello");
    public string Value3 => "Hello";
}
class Program
{
    static void Main(string[] args)
    {
        Text text = new Text();
        Console.WriteLine(ReferenceEquals(text.Value1, text.Value1));
        Console.WriteLine(ReferenceEquals(text.Value2, text.Value2));
        Console.WriteLine(ReferenceEquals(text.Value3, text.Value3));
    }
}

Да и код работает на языке C# 8.0 и выше, .netCore 3.1

Ответ True,False,True

Дело в том, что Object.ReferenceEquals(Object, Object) вернет значение true, если параметр objA соответствует тому же экземпляру, что и параметр objB, или же оба они являются равны NULL; в противном случае — значение false.

В строке

public string Value2 => new string("Hello");

создается новый экземпляр. Потому и false.

Объясните пожалуйста, что это за конструкция такая с лямбда выражением? Я впервые такое вижу. Зачем вообще нужна такая конструкция и когда ее используют? Получается всегда, когда мы обращаемся к полю класса, вызывается лямбда выражение и вычисляется значение. Бессмыслица какая-то.


Ответы (1 шт):

Автор решения: Exploding Kitten

=> (стрелочная функция, лямбда выражение) - это по факту синтаксический сахар (упрошение) для удобства разработчика, в вашем случае, который равен:

public class Text
{
    [CompilerGenerated]
    private readonly string <Value1>k__BackingField = new string("Hello");

    public string Value1
    {
        [CompilerGenerated]
        get
        {
            return <Value1>k__BackingField;
        }
    }

    public string Value2
    {
        get
        {
            return new string("Hello");
        }
    }

    public string Value3
    {
        get
        {
            return "Hello";
        }
    }
}

Отсюда и true, false, true результат, т.к.:

  • в первом случает, у вас один и тотже объект (сравнивается абсолютна одна и таже переменная), поэтому и true
  • во втором случае, код создает каждый раз новую строку, сколько раз будет вызвано раз свойство Value2 стольно и будет разных объектов, получается при вызове ReferenceEquals(text.Value2, text.Value2) будет создано 2 объекта
  • в третьем случае будет true из-за интернирования строк, при компиляцие C#, все строки (константные строки, литералы) будут автоматичски обработаны так, что будут ссылать на один объект, т.к. строки не изменяемые, то нет смысла каждый раз создавать новый объект.
→ Ссылка