То, что вы записываете в файл - это не строка, а внутренняя структура объекта std::string
. Скорее всего, это указатель. Когда вы прочитаете его обратно, указатель будет указывать на что-то недопустимое. Тебе повезло, что ты получил хоть какой-то выход, а не аварию или демонов, летящих из твоих ноздрей.
Одна из самых важных вещей, которые я изучил, - то, что можно ограничить универсальный параметр (параметры) типа. Это может быть очень мощно, разрешение Вам взять настраивает класс только для определенных типов объектов и разрешения Вам использовать членов того типа в Вашем универсальном классе. Я понимаю, что это довольно фундаментально, но это - одна из вещей, которая делает дженерики невероятно полезными.
Каждую специализацию универсального типа рассматривают как уникальный тип когда дело доходит до вещей как статические участники. Например, с этим типом:
class GenericType<T>
{
public static int SomeValue;
}
Утверждение успешно выполняется, если мы делаем это:
GenericType<int>.SomeValue = 3;
Debug.Assert(GenericType<double>.SomeValue == 0);
Это вызвано тем, что:
typeof(GenericType<int>) != typeof(GenericType<double>)
Даже при том, что
typeof(GenericType<int>.GetGenericTypeDefinition() == typeof(GenericType<double>).GetGenericTypeDefinition()
Поймите возможности и ограничения универсального вывода типа в C#. Глубокое понимание того, что не может компилятор, и, может вывести на основе (например). типы параметров в Вашем методе могут быть усилены для создания общих примеров использования API значительно более читаемыми.
Никакая ковариантность или контравариантность (по крайней мере, в 3,5). Знайте об этом при разработке иерархий классов, которые включают универсальные параметры типа.
Самый важный урок о дженериках, которые я изучил: чем больше Вы используете их, тем лучше.
Два интересных урока. Сначала; со списками; попытайтесь думать с точки зрения T
; поскольку полное изложение видит здесь, но короче говоря необходимо использовать:
public void Foo<T>(IList<T> data) where T : SomeBaseClassOrInterface {}
и нет:
public void Foo(IList<SomeBaseClassOrInterface> data) {}
Во-вторых: наблюдайте за пограничными случаями;-p
Можно ли видеть прерывание здесь?
static void Foo<T>() where T : new()
{
T t = new T();
Console.WriteLine(t.ToString()); // works fine
Console.WriteLine(t.GetHashCode()); // works fine
Console.WriteLine(t.Equals(t)); // works fine
// so it looks like an object and smells like an object...
// but this throws a NullReferenceException...
Console.WriteLine(t.GetType()); // BOOM!!!
}
Не знайте, являются ли они самыми важными, но я изучил следующее:
Дженерики только будут instantiable через отражение, если Вы не будете знать тип frikkin. В некоторых случаях Вам, возможно, понадобятся неуниверсальные интерфейсы для использования универсальных классов в ситуациях, где тип неизвестен.
Я почти разрушил голову пока я grocked это
public class Foo<T> where T : Foo<T> {
public T CloneMe() ...
}
совершенно действительный код и позволяет Вашему базовому классу выставлять методы и свойства, связанные со специализированным классом... это закончилось в определении конечного автомата вдоль его состояний:
public abstract class Machine<S,M> where S : State<S,M> where M : Machine<S,M> {
protected S state;
}
public abstract class State<S,M> where S : State<S,M> where M : Machine<S,M> {
protected M machine;
}
Дженерики могут стать немного громоздкими. На днях у меня было это:
List<Tuple<Expression<Func<DataTable,object>>,Expression<Func<DataTable,object>>>>
уф...
В первую очередь, важно знать, как Дженерики работают в C#. Эта статья дает Вам хороший обзор дженериков Anders Hejlsberg (Родительский элемент c#). Я не думаю, что использование их максимально часто настолько хорошо. Используйте дженерики, когда они действительно будут иметь смысл. Всегда помните KISS, и YAGNI (Сохраните Его Простым Глупый; Вы не Собирается Потребность Это) от экстремального программирования.
Я узнал, что дженерики являются indeep мощным инструментом, все же неправильно используемым, приводит к очень нечитабельному коду.
Универсальные типы делегата всегда являются инвариантом типа.
Я столкнулся с проблемой, подобной тому, что обрисовано в общих чертах в ссылке ниже на днях, и она вызвала некоторый беспорядок, потому что я не понял, почему я должен был бросить свой набор.
http://www.theserverside.net/blogs/thread.tss?thread_id=47323
MyGeneric<T> where T : IComparable
не делает
MyGeneric<IComparable>
базовый класс его.