Есть ли какие-либо серьезные основания, почему закрытия не неизменны в C#?

Используйте MSAL для учетных записей Microsoft.

https://github.com/AzureAD/microsoft-authentication-library-for-js/tree/dev/lib/msal-angular

6
задан GEOCHET 27 February 2009 в 17:52
поделиться

6 ответов

C# и JavaScript, а также O'Caml и Haskell, и много других языков, имеют то, что известно как лексические закрытия. Это означает, что внутренние функции могут получить доступ к названиям локальных переменных в функциях включения, не только копиям значений. На языках с неизменными символами, конечно, такими как O'Caml или Haskell, закрывающийся по именам, идентично закрытию по значениям, таким образом, различие между двумя типами закрытия исчезает; эти языки, тем не менее, имеют лексические закрытия точно так же, как C# и JavaScript.

9
ответ дан 8 December 2019 в 16:10
поделиться

Не все закрытия ведут себя то же. Существуют различия в семантике.

Обратите внимание, что первая идея представила, соответствует поведению C#... Ваше понятие семантики закрытия не может быть преобладать понятием.

Что касается причин: Я думаю, что ключом здесь является ECMA, группа стандартов. Microsoft просто следует за их семантикой в этом случае.

3
ответ дан 8 December 2019 в 16:10
поделиться

Необходимо также помнить, что в C# нет действительно никакого понятия неизменных типов. Поскольку целые объекты в платформе .NET просто не становятся скопированными (необходимо явно реализовать ICloneable, и т.д.), этот код распечатал бы "до свидания", даже если бы нечто "указателя" было скопировано в закрытии:

class Foo
{
    public string Text;
}    
var foo = new Foo();
foo.Text = "Hello";
Action bar = () => Console.WriteLine(foo.Text);
bar();
foo.Text = "goodbye";
bar();

Так его сомнительное, если в текущем поведении легче получить непреднамеренные последствия.

1
ответ дан 8 December 2019 в 16:10
поделиться

Это - на самом деле фантастическая функция. Это позволяет Вам иметь закрытие, которое получает доступ к чему-то обычно скрытому, скажем, частная переменная класса, и позвольте ему управлять им управляемым способом как ответ на что-то как событие.

Можно моделировать то, что Вы хотите довольно легко путем создания локальной копии переменной и использования этого.

2
ответ дан 8 December 2019 в 16:10
поделиться

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

[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
    public string foo;

    public void <Main>b__0()
    {
        Console.WriteLine(this.foo);
    }
}

Вашему делегату дают ссылку на этот тип так, чтобы он мог использовать полученные переменные позже. К сожалению, локальный экземпляр foo также изменяется для указания здесь, таким образом, любые изменения локально будут влиять на делегата, поскольку они используют тот же объект.

Поскольку Вы видите персистентность foo обрабатывается общедоступным полем, а не свойством, таким образом, даже нет опции неизменности здесь с текущей реализацией. Я думаю, что Вы хотите, должно было бы быть что-то вроде этого:

var foo = "hello";
Action bar = [readonly foo]() => Console.WriteLine(foo);
bar();
foo = "goodbye";
bar();

Простите неуклюжий синтаксис, но идея состоит в том, чтобы обозначить это foo получен в a readonly вид, который затем подсказал бы компилятору для вывода этого сгенерированного типа:

[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
    public readonly string foo;

    public <>c__DisplayClass1(string foo)
    {
        this.foo = foo;
    }

    public void <Main>b__0()
    {
        Console.WriteLine(this.foo);
    }
}

Это дало бы Вам, что Вы хотели определенным способом, но потребуете обновлений компилятора.

0
ответ дан 8 December 2019 в 16:10
поделиться

Что касается , почему являются изменяемыми замыканиями в C #, вы должны спросить: «Вам нужна простота (Java) или мощь со сложностью (C #)?»

Изменяемые замыкания позволяют определять один раз и использовать повторно. Пример:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClosureTest
{
    class Program
    {   
        static void Main(string[] args)
        {
            string userFilter = "C";            
            IEnumerable<string> query = (from m in typeof(String).GetMethods()
                                         where m.Name.StartsWith(userFilter)
                                         select m.Name.ToString()).Distinct();

            while(userFilter.ToLower() != "q")
            {
                DiplayStringMethods(query, userFilter);
                userFilter = GetNewFilter();
            }
        }

        static void DiplayStringMethods(IEnumerable<string> methodNames, string userFilter)
        {
            Console.WriteLine("Here are all of the String methods starting with the letter \"{0}\":", userFilter);
            Console.WriteLine();

            foreach (string methodName in methodNames)
                Console.WriteLine("  * {0}", methodName);
        }

        static string GetNewFilter()
        {
            Console.WriteLine();
            Console.Write("Enter a new starting letter (type \"Q\" to quit): ");
            ConsoleKeyInfo cki = Console.ReadKey();
            Console.WriteLine();
            return cki.Key.ToString();
        }
    }
}

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

        string userFilter = "C";
        string userFilter_copy = userFilter;
        IEnumerable<string> query = (from m in typeof(String).GetMethods()
                                     where m.Name.StartsWith(userFilter_copy)
                                     select m.Name.ToString()).Distinct();

Теперь запрос будет возвращать тот же результат, независимо от того, чему равен userFilter .

Джон Скит отлично знакомит с различиями между Java и C #. закрытие .

0
ответ дан 8 December 2019 в 16:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: