Каким образом создать клон 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());
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Каким образом создать клон StringBuilder наименее затратным для процессора способом?
А> = new StringBuilder(string value) А>Оно?
Здравствуйте, 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;
}
}
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>>Каким образом создать клон StringBuilder наименее затратным для процессора способом?
А>Самый быстрый способ new StringBuilder(oldObj.ToString()). Он даже быстрее чем ShallowCopy.
Справедливости ради. Забыт параметр Capacity — дабы новый билдер имел внутри себя буфер такого же размера, как и исходный.
Здравствуйте, hardcase, Вы писали:
H>Справедливости ради. Забыт параметр Capacity — дабы новый билдер имел внутри себя буфер такого же размера, как и исходный.
Если строка передается, то можно не указывать capacity, т.к. там в конструкторе есть проверка