запись встречи от 24/02/2012

Содержание
частично определенные классы
just-in-time компилятор и сборщик мусора
лямбда-функции
обобщенные классы
этот странный ArraySegment

  • частично определенные классы (см. также на msdn)
Частичные определенная позволяют дополнять определение классов. Например:
partial class A {
    static void f() {}
    static void f2() {}
}
partial class A {
    public void g() {}
    public void g2() {}
}

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

  • just-in-time компилятор и сборщик мусора
см. книгу Рихтера CLR via C#

  • лямбда-функции (см.также на msdn)
Лямбда-функции в C# можно использовать для функций высших порядков. Активно лямбда-функции используются в LINQ.
Приведем пример использования функции высшего порядка для операции свертки:
Определим статичный класс с функцией свертки:
static class Fun 
{
    // можно и так:
    // public delegate Y accfun<T,Y>(Y acc, T x);
    // public static Y fold<T,Y>(T []xs, accfun<T,Y> f, Y acc) 
    public static Y fold<T, Y>(T[] xs, Func<Y, T, Y> f, Y acc)
    {
        foreach (var x in xs)
        {
            acc = f(acc, x);
        }
        return acc;
    }
}
Пример использования
// используем fold для суммы всех элементов
var x = Fun.fold(new int[] { 1, 2, 3, 4 }, (a, b) => a + b, 0);
// ищем максимальный элемент в последовательности
var y = Fun.fold(new int[] { 1, 2, 3, 4 }, (a, b) => a > b ? a : b, 0);
// фильтруем массив, оставляя в нем только положительные элементы
var z = Fun.fold(new int[] { 1, -2, 3, -4 },
    (a, b) => { if (b > 0) a.Add(b); return a; },
    new ArrayList());

System.Console.Out.WriteLine(x);
System.Console.Out.WriteLine(y);
System.Console.Out.Write(z[0]);
System.Console.Out.Write(",");
System.Console.Out.WriteLine(z[1]);
На экране мы увидим, соответственно, следующее
10
4
1,3

  • обобщенные классы (см. также на msdn)
Обобщенные классы появились в C# начиная с версии .net-2.0. Можно сказать, что это аналог шаблонов из С++ с некоторыми изменениями. В C# тип-параметр может содержать только те методы, которые явно указаны в интерфейсе(или классе), записанном после where:
class A<T> where T: IA, new()
{
    T a;
    A<T>() {
        this.a = new T();
    }
    void doit() {
        a.f1();
    }
}
Фраза "new()" означает, что объект типа T должен содержать публичный конструктор. Определим интерфейс IA, который включает в себя метод "f1".
interface IA 
{
    void f1();
}

Пример использования:
class B : IA {
    public void f1() {}
}
var ab = new A<B>();
Раз в классе A было указано, что тип T должен быть инстанцируемым (т.е. содержать публичный конструктор), то необходимо определить класс "B", реализующий методы интерфейса IA.

Если не указывать, от каких интерфейсов/классов должен наследоваться тип-параметр, то тип-параметр по умолчанию считается наследником корневого класса Object.

  • этот странный ArraySegment (см. также на msdn)
В .net-фреймворке есть структура ArraySegment, позволяющая использовать некоторый аналог слайсов в C#. Пример использования:
var x = new int[]{1,2,3,4};
var s = new ArraySegment<int>(x, 1,2);
System.Console.Out.WriteLine(x[1]);
s.Array[s.Offset] = 44;
System.Console.Out.WriteLine(x[1]);
На экране мы увидим в этом случае
2
44

Не считая неудобства использования элементов слайса через поле Array, в ArraySegment, к сожалению, не поддерживается и перечисление циклом foreach. В качестве замены можно использовать класс DelimitedArray из статьи ArraySegment Structure - what were they thinking?

Last edited Feb 27, 2014 at 10:28 AM by basph, version 27

Comments

No comments yet.