Клонирование StringBuilder
От: Аноним  
Дата: 19.01.12 11:43
Оценка:
Каким образом создать клон StringBuilder наименее затратным для процессора способом?

1. Можно переопределить StringBuilderExt: StringBuilder, ICloneable

public StringBuilderExt ICloneable.Clone() // implement method
{
  MemoryStream ms = new MemoryStream(); // create MemoryStream
  BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone))
  bf.Serialize(ms, this)
  ms.Seek(0, SeekOrigin.Begin)
  StringBuilderExt obj;
  obj = (StringBuilderExt) bf.Deserialize(ms);
  ms.Close();
  return obj;
}


2. Можно вызывать стороннюю Generic функцию такого вида:
        private T CreateShallowCopy<T>(T o)
        {
            // Поверхностное клонирование.
            MethodInfo memberwiseClone = o.GetType().GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);

            // Вызов метода MemberwiseClone из-под объекта o.
            return (T)memberwiseClone.Invoke(o, null);
        }

        private T CreateDeepCopy<T>(T o)
        {
            // Создаем поверхостную копию.
            T copy = CreateShallowCopy(o);

            // Получем массив объектов FieldInfo и проходим по всем полям.
            foreach (FieldInfo f in typeof(T).GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
            {
                // Получаем значение хранящееся в поле класса.
                object original = f.GetValue(o);

                // Устанавливаем значение в поле объекта copy cо значением которое будет установлено с помощью рекурсивного вызова метода.
                f.SetValue(copy, CreateDeepCopy(original));
            }
            return copy;
        }

3. Либо представленную в п.1, с копированием через MemoryStream
4. Можно создавать новый экземпляр так

StringBuilder newObj= new StringBuilder(oldObj.ToString());


5. Или через массив.

Подскажите какой метод менее ресурсоемкий?
Re: Клонирование StringBuilder
От: Lloyd Россия  
Дата: 19.01.12 11:56
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Подскажите какой метод менее ресурсоемкий?


А почему бы самому не померить?
Re: Клонирование StringBuilder
От: Аноним  
Дата: 19.01.12 11:57
Оценка: +1
Здравствуйте, Аноним, Вы писали:

А>Каким образом создать клон StringBuilder наименее затратным для процессора способом?


= new StringBuilder(string value)
Оно?
Re[2]: Клонирование StringBuilder
От: Mihas  
Дата: 19.01.12 12:01
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


А>>Каким образом создать клон StringBuilder наименее затратным для процессора способом?


А> = new StringBuilder(string value)

А>Оно?

Ну это, наверное, самый затратный способ.
Re[3]: Клонирование StringBuilder
От: debugx Россия http://oignatov.blogspot.com
Дата: 19.01.12 12:10
Оценка:
Здравствуйте, Mihas, Вы писали:

M>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, Аноним, Вы писали:


А>>>Каким образом создать клон StringBuilder наименее затратным для процессора способом?


А>> = new StringBuilder(string value)

А>>Оно?

M>Ну это, наверное, самый затратный способ.


по логике вещей наоборот самый быстрый, так как в потроха не лезем
хотя может можно и быстрей.
Re: Клонирование StringBuilder
От: Аноним  
Дата: 19.01.12 12:33
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Каким образом создать клон StringBuilder наименее затратным для процессора способом?


Самый быстрый способ new StringBuilder(oldObj.ToString()). Он даже быстрее чем ShallowCopy.


    public static class Ext
    {
        public static T Clone<T>(this T obj) // implement method
        {
            MemoryStream ms = new MemoryStream(); // create MemoryStream
            BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
            bf.Serialize(ms, obj);
            ms.Seek(0, SeekOrigin.Begin);
            T newObj = (T)bf.Deserialize(ms);
            ms.Close();
            return newObj;
        }

        private static T CreateShallowCopy<T>(T o)
        {
            // Поверхностное клонирование.
            MethodInfo memberwiseClone = o.GetType().GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);

            // Вызов метода MemberwiseClone из-под объекта o.
            return (T)memberwiseClone.Invoke(o, null);
        }

        public static T CreateDeepCopy<T>(this T o)
        {
            // Создаем поверхостную копию.
            T copy = CreateShallowCopy(o);

            // Получем массив объектов FieldInfo и проходим по всем полям.
            foreach (FieldInfo f in typeof(T).GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
            {
                // Получаем значение хранящееся в поле класса.
                object original = f.GetValue(o);
                if (ReferenceEquals(original, null))
                    f.SetValue(copy, null);
                else
                // Устанавливаем значение в поле объекта copy cо значением которое будет установлено с помощью рекурсивного вызова метода.
                    f.SetValue(copy, CreateDeepCopy(original));
            }
            return copy;
        }
    }

    [TestFixture]
    public class Class1
    {
        public StringBuilder Clone<StringBuilder>(StringBuilder obj) // implement method
        {
            MemoryStream ms = new MemoryStream(); // create MemoryStream
            BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
            bf.Serialize(ms, obj);
            ms.Seek(0, SeekOrigin.Begin);
            StringBuilder newObj = (StringBuilder)bf.Deserialize(ms);
            ms.Close();
            return newObj;
        }

        private T CreateShallowCopy<T>(T o)
        {
            // Поверхностное клонирование.
            MethodInfo memberwiseClone = o.GetType().GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic);

            // Вызов метода MemberwiseClone из-под объекта o.
            return (T)memberwiseClone.Invoke(o, null);
        }

        public T CreateDeepCopy<T>(T o)
        {
            // Создаем поверхостную копию.
            T copy = CreateShallowCopy(o);

            // Получем массив объектов FieldInfo и проходим по всем полям.
            foreach (FieldInfo f in typeof(T).GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
            {
                // Получаем значение хранящееся в поле класса.
                object original = f.GetValue(o);

                if (ReferenceEquals(original,null))
                    f.SetValue(copy,null);
                else
                // Устанавливаем значение в поле объекта copy cо значением которое будет установлено с помощью рекурсивного вызова метода.
                    f.SetValue(copy, CreateDeepCopy(original));
            }
            return copy;
        }

        [Test]
        public void Test1()
        {
            IList<StringBuilder> source = new List<StringBuilder>();
            for (int i = 0; i<100000;i++)
            {
                source.Add(new StringBuilder("abcd" + i.ToString()));
            }

            //
            IList<StringBuilder> dest1 = new List<StringBuilder>();

            DateTime dt1 = DateTime.Now;

            foreach (StringBuilder stringBuilder in source)
            {
                dest1.Add(stringBuilder.Clone());
            }

            DateTime dt2 = DateTime.Now;

            for (int i = 0; i < dest1.Count; i++)
            {
                if (source[i].ToString() != dest1[i].ToString())
                    Assert.Fail();
            }

            //
            IList<StringBuilder> dest2 = new List<StringBuilder>();

            DateTime dt3 = DateTime.Now;

            foreach (StringBuilder stringBuilder in source)
            {
                dest2.Add(stringBuilder.CreateDeepCopy());
            }

            DateTime dt4 = DateTime.Now;

            for (int i = 0; i < dest2.Count; i++)
            {
                if (source[i].ToString() != dest2[i].ToString())
                    Assert.Fail();
            }

            //
            IList<StringBuilder> dest3 = new List<StringBuilder>();

            DateTime dt5 = DateTime.Now;

            foreach (StringBuilder stringBuilder in source)
            {
                dest3.Add(new StringBuilder(stringBuilder.ToString()));
            }

            DateTime dt6 = DateTime.Now;

            for (int i = 0; i < dest3.Count; i++)
            {
                if (source[i].ToString() != dest3[i].ToString())
                    Assert.Fail();
            }

            //
            IList<StringBuilder> dest4 = new List<StringBuilder>();

            DateTime dt7 = DateTime.Now;

            foreach (StringBuilder stringBuilder in source)
            {
                dest4.Add(Clone(stringBuilder));
            }

            DateTime dt8 = DateTime.Now;

            for (int i = 0; i < dest4.Count; i++)
            {
                if (source[i].ToString() != dest4[i].ToString())
                    Assert.Fail();
            }

            //
            IList<StringBuilder> dest5 = new List<StringBuilder>();

            DateTime dt9 = DateTime.Now;

            foreach (StringBuilder stringBuilder in source)
            {
                dest5.Add(CreateDeepCopy(stringBuilder));
            }

            DateTime dt10 = DateTime.Now;

            for (int i = 0; i < dest5.Count; i++)
            {
                if (source[i].ToString() != dest5[i].ToString())
                    Assert.Fail();
            }

            //
            IList<StringBuilder> dest6 = new List<StringBuilder>();

            DateTime dt11 = DateTime.Now;

            foreach (StringBuilder stringBuilder in source)
            {
                dest6.Add(CreateShallowCopy(stringBuilder));
            }

            DateTime dt12 = DateTime.Now;

            for (int i = 0; i < dest6.Count; i++)
            {
                if (source[i].ToString() != dest6[i].ToString())
                    Assert.Fail();
            }

            TimeSpan ts1 = dt2 - dt1;
            TimeSpan ts2 = dt4 - dt3;
            TimeSpan ts3 = dt6 - dt5;
            TimeSpan ts4 = dt8 - dt7;
            TimeSpan ts5 = dt10 - dt9;
            TimeSpan ts6 = dt12 - dt11;
        }
    }
Re[2]: Клонирование StringBuilder
От: hardcase Пират http://nemerle.org
Дата: 19.01.12 15:06
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


А>>Каким образом создать клон StringBuilder наименее затратным для процессора способом?


А>Самый быстрый способ new StringBuilder(oldObj.ToString()). Он даже быстрее чем ShallowCopy.


Справедливости ради. Забыт параметр Capacity — дабы новый билдер имел внутри себя буфер такого же размера, как и исходный.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[3]: Клонирование StringBuilder
От: Димчанский Литва http://dimchansky.github.io/
Дата: 19.01.12 16:04
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Справедливости ради. Забыт параметр Capacity — дабы новый билдер имел внутри себя буфер такого же размера, как и исходный.


Если строка передается, то можно не указывать capacity, т.к. там в конструкторе есть проверка
if (capacity < length) 
    capacity = length;
... << RSDN@Home 1.2.0 alpha 5 rev. 1536>>
Re[4]: Клонирование StringBuilder
От: hardcase Пират http://nemerle.org
Дата: 19.01.12 16:12
Оценка:
Здравствуйте, Димчанский, Вы писали:

Д>Если строка передается, то можно не указывать capacity, т.к. там в конструкторе есть проверка

Д>
if (capacity < length) 
Д>    capacity = length;


Строка полученная от старого билдера может быть меньше его текущей вместимости. Но это все мелочи
/* иЗвиНите зА неРовнЫй поЧерК */
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.