Анонимные методы, объем и сериализация

Действительно интересный вопрос. Честно я не могу доказать, почему объекты хороши. Но я могу совместно использовать свое мнение, почему мне нравятся они. Код как

void exportOrder(Order order, String fileName){...};

не затронут, куда порядок прибыл из - от DB, из веб-запроса, от модульного теста, и т.д. Это заставляет этот метод более явно объявить то, чего точно это требует, вместо того, чтобы брать DataRow и документировать, какие столбцы это ожидает иметь и который вводит, они должны быть. То же применяется при реализации его так или иначе как хранимой процедуры - все еще необходимо продвинуть рекордный идентификатор к нему, в то время как это не необходимый должно присутствовать в DB.

Реализация этого метода была бы сделана на основе абстракции Порядка, не на основе того, как точно это представлено в DB. Большинство таких операций, которые я реализовал действительно, не зависит от того, как эти данные хранятся. Я действительно понимаю, что некоторые операции требуют связи со структурой DB для производительности и целей масштабируемости, просто по моему опыту, нет слишком большого количества из них. По моему опыту, очень часто достаточно знать, что у Человека есть .getFirstName () возвращающий Строку и .getAddress () возвращающий Адрес, и адрес имеет .getZipCode (), и т.д. - и не заботьтесь, какие таблицы являются involed, чтобы хранить те данные.

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

Масштабируемость является интересным моментом здесь - большинство веб-сайтов, которые требуют, чтобы огромная масштабируемость (как Facebook, Живой Журнал, flickr) имела тенденцию использовать аскетический DB подход, когда DB используется максимально редкий, и проблемы масштабируемости решены путем кэширования, особенно Использованием оперативной памяти. http://highscalability.com/ имеет некоторые интересные статьи о нем.

5
задан Stefan Moser 14 August 2009 в 18:10
поделиться

4 ответа

Обновление: чтобы увидеть, что на самом деле происходит, не прибегая к IL: Использование отражателя для понимания анонимных методов и захваченных переменных


Когда вы используете:

public Bar CreateBar()
{
    return new Bar(x, () => y);
}

Вы неявно значение this.y ; поэтому с точки зрения делегата включена ссылка на Foo . Таким образом, экземпляр Bar (через делегата) сохраняет весь Foo живым (не собираемым мусором) до тех пор, пока Bar не станет доступным для сбора. 12143] В частности, компилятору нет необходимости (в этом случае) создавать дополнительный класс для обработки захваченных переменных; единственное, что требуется, это экземпляр Foo , поэтому метод может быть сгенерирован на Foo . Это было бы сложнее, если бы делегат включал локальные переменные (кроме this ).

Что касается сериализации ... ну, первое, что я бы сказал, это то, что сериализация делегатов - это очень очень плохая идея. Однако BinaryFormatter будет обходить делегаты, и вы можете (теоретически) получить сериализованный Bar , сериализованный Foo и сериализованный делегат чтобы связать их - но только , если вы отметите Foo как [Serializable] .

Но я подчеркиваю - это плохая идея . Я редко использую BinaryFormatter (по разным причинам), но люди, использующие его, часто спрашивают: «Почему он пытается сериализовать (какой-то случайный тип)». Обычно ответ такой: «вы публикуете мероприятие, другой способ исследовать это - использовать отражатель в режиме .NET 1.0 (то есть без его замены анонимными методами); тогда вы можете увидеть:

public Bar CreateBar()
{
    return new Bar(this.x, new Func<int>(this.<CreateBar>b__0));
}
[CompilerGenerated]
private int <CreateBar>b__0()
{
    return this.y;
}

Как видите; вещь, переданная в Bar , является делегатом скрытого метода (называемого b__0 () ) в текущем экземпляре ( this ). Таким образом, - это экземпляр текущего Foo , который передается в Bar .

другой способ исследовать это - использовать отражатель в режиме .NET 1.0 (то есть без его замены анонимными методами); тогда вы можете увидеть:

public Bar CreateBar()
{
    return new Bar(this.x, new Func<int>(this.<CreateBar>b__0));
}
[CompilerGenerated]
private int <CreateBar>b__0()
{
    return this.y;
}

Как видите; вещь, переданная в Bar , является делегатом скрытого метода (называемого b__0 () ) в текущем экземпляре ( this ). Таким образом, - это экземпляр текущего Foo , который передается в Bar .

5
ответ дан 14 December 2019 в 13:43
поделиться

Создайте проект быстрой проверки для вывода значений, а затем просмотрите их. Он должен ответить на вопросы и, вероятно, побудить вас узнать что-то дополнительное в процессе. (Это то, что сделали большинство людей, которые ответят на ваш вопрос.)

0
ответ дан 14 December 2019 в 13:43
поделиться

У меня возникла ошибка при попытке сериализации, когда она отражала объект для сериализации.

мой пример:

[Serializable]
    public class SerializeTest
    {
        //public SerializeTest(int a, Func<int> b)
        //{
        //    this.a = a;
        //    this.b = b;
        //}

        public SerializeTest()
        {

        }

        public int A 
        {
            get
            {
                return a;
            }

            set
            {
                a = value;
            }
        }
        public Func<int> B 
        {
            get
            {
                return b;
            }
            set
            {
                b = value;
            }
        }


        #region properties

        private int a;
        private Func<int> b;



        #endregion

        //serialize itself
        public string Serialize()
        {
            MemoryStream memoryStream = new MemoryStream();

            XmlSerializer xs = new XmlSerializer(typeof(SerializeTest));
            using (StreamWriter xmlTextWriter = new StreamWriter(memoryStream))
            {
                xs.Serialize(xmlTextWriter, this);
                xmlTextWriter.Flush();
                //xmlTextWriter.Close();
                memoryStream = (MemoryStream)xmlTextWriter.BaseStream;
                memoryStream.Seek(0, SeekOrigin.Begin);
                StreamReader reader = new StreamReader(memoryStream);

                return reader.ReadToEnd();
            }
        }

        //deserialize into itself
        public void Deserialize(string xmlString)
        {
            String XmlizedString = null;

            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (StreamWriter w = new StreamWriter(memoryStream))
                {
                    w.Write(xmlString);
                    w.Flush();

                    XmlSerializer xs = new XmlSerializer(typeof(SerializeTest));
                    memoryStream.Seek(0, SeekOrigin.Begin);
                    XmlReader reader = XmlReader.Create(memoryStream);

                    SerializeTest currentConfig = (SerializeTest)xs.Deserialize(reader);

                    this.a = currentConfig.a;
                    this.b = currentConfig.b;

                    w.Close();
                }
            }
        }

    }

class Program
    {
        static void Main(string[] args)
        {

            SerializeTest test = new SerializeTest() { A = 5, B = ()=>67};
            string serializedString =  test.Serialize();


}
}

Вот ссылка на это ... немного сложнее: Сериализация анонимных делегатов

1
ответ дан 14 December 2019 в 13:43
поделиться

Я думаю, что x и y в объекте Foo будут захвачены как типы значений. Таким образом, закрытие, созданное для этого лямбда-выражения, не должно содержать ссылку на объект Foo. Таким образом, компилятор может создать класс для этого закрытия, например:

internal class CompilerGeneratedClassName
{
   private int x;
   private int y;
   public CompilerGeneratedClassName(int x, int y)
   {
     this.x = x;
     this.y = y;
   }

   public int CompilerGeneratedMethodName()
   {
     return this.y;
   }     
}

и

return new Bar(x, () => y); 

могут быть заменены на

return new Bar(x,new CompilerGeneratedClassName(x,y).CompilerGeneratedMethodName);

Так что я не думаю, что в результате этого закрытия будет ссылка на объект Foo. Итак, объект Foo может быть собран. Я могу ошибаться. Единственное, что вы можете сделать, - это написать небольшую программу, скомпилировать ее и проверить сгенерированный IL с помощью инструмента ILDASM.

0
ответ дан 14 December 2019 в 13:43
поделиться
Другие вопросы по тегам:

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