4 заметки с тегом

csharp

MacGreener C#

MacGreener C# (36.34КиБ)

Переписал МакГринер с Си на Си#. Основной код более-менее повторяется, но код получился более чем в два раза длинее.

Весь код разбит, преимущественно, на три класса — основной класс, где выполняется приложение, класс IOKit — низкоуровневые и чуть более высокоуровневые биндинги для библиотек МакОСи и IOKitMotionSensor — ещё более высокоуровневая обёртка над куском кода для опроса датчика.

Есть ещё два вспомогательных класса — IOKitException, класс кидаемых исключений и IOKitObject — класс всех ресурсов, которые требуется высвобождать (он следит за своевременным их высвобождением при помощи блока using).

Не знаю какую версию я буду дальше развивать (и буду ли), но версия на Си# более прожорлива — из-за фреймворка Mono, который требуется для исполнения программ на этом языке. Версия на Си# занимает в памяти 6,2Мб (+49,8Мб виртуальной), на Си — 840Кб (+18,6Мб виртуальной).

Хорошо, что мой братишка давно программирует на этом языке, с его консультациями в некоторых тонкостях удаётся разобраться быстрее.

Первые эксперименты с C#

Поучился обращаться к динамическим библиотекам «Мака» (dylib) из Си-шарпа. Не очень удобно, надо сказать. Вот во что превратилась моя функция macSleepAwake из сишной программы MacGreener:

using System; 
using System.Runtime.InteropServices;
using MonoMac;
using MonoMac.CoreFoundation;
using MonoMac.ObjCRuntime;

namespace MacGreenerFragment
{
    class SleepAwake
    {
        [DllImport ("IOKit", CharSet = CharSet.Ansi)]
        static extern int IORegistryEntryFromPath (IntPtr masterPort, string path);

        [DllImport ("IOKit")]
        static extern void IOObjectRelease (int @object);

        [DllImport ("IOKit")]
        static extern void IORegistryEntrySetCFProperty(int entry, IntPtr propertyName, IntPtr property);

        static void macSleepAwake(bool sleep)
        {
            var handle   = Dlfcn.dlopen (Constants.CoreFoundationLibrary, 0);
            IntPtr True  = Dlfcn.GetIntPtr (handle, "kCFBooleanTrue");
            IntPtr False = Dlfcn.GetIntPtr (handle, "kCFBooleanFalse");

            int r = IORegistryEntryFromPath(IntPtr.Zero, "IOService:/IOResources/IODisplayWrangler");
            if (r != 0) {
                IORegistryEntrySetCFProperty(r, ((CFString)"IORequestIdle").Handle, sleep ? True : False);
                IOObjectRelease(r);
            }
        }
    }
}

На Си это 11 строк.

Шутка про женщин на C#

Придумалась шутка про женщин на языке Си-шарп:

class Woman {
    public static bool operator true (Woman question) {
        return false;
    }

    public static bool operator false (Woman question) {
        return false;
    }
}
2013   csharp

Идентификаторы в C#

Я тут Си-шарп начал учить, удивляюсь всему, как ребёнок, с первых же страниц.

Идентификаторы (42.74КиБ)

Обратите внимание на строку 9, тут любопытно, я встречал языки, где в качестве имён переменных можно использовать символы Юникода (тот же ПХП), а тут, мало того, можно писать юникодные символы с использованием слеш-ю-нотации!

Например, у меня, в качестве имени переменной, используется символ «усмехающееся кошачье лицо со смешинками в глазах» (не всем видно будет — 😸). Со вторым идентификатором ещё интереснее.

Если вам нужно использовать в качестве идентификатора зарезервированное слово (ну вот надо, а максимально подходящее английское слово является зарезервированным), можно предварить его «собачкой» и в таком виде использовать (см. строку 10).

Программа выше компилируется и выполняется без ошибок.

А вот вещь по которой я скучал: фигурные скобки создают локальную область видимости (как в Перле), правда я не могу определить переменную в этом блоке, которая уже есть в локальном блоке выше, причём только до замыкания, удивительное правило.

Ну да ладно, в общем, вот такой код не скомпилируется, будет ошибка в последней строке, сообщающая об отсутствие переменной @string:

{
    string @string = @"string ""string""";
    Console.WriteLine (@string.Insert (1, "tt"));
}

Console.WriteLine (@string); // ошибка!

Вещь, с которой не ожидал столкнуться — автоматическое приведение типов. Я как-то был уверен (о Си-шарпе я только слышал, но ничего определённого не знал), что тут будет как в Гоу или Си — нужно преобразовывать переменные к какому-то единому типу, а уже потом что-то с ним делать. Оказалось, ничего подобного:

byte байтраз = 3, байтдва = 5;

// строка кода ниже выведет System.Int32 (а не System.Byte, как я ожидал)
// арифметические операции определены только для типов int и больше,
// поэтому произойдёт преобразование типов
Console.WriteLine ((байтраз + байтдва).GetType());

Console.WriteLine ("Первый байт равен: " + байтраз); // строки спокойно складываются с числами

Ещё интересная вещь — отключение проверки переполнения (в нормальной ситуации вызовется исключение), видимо для совместимости с сишным поведением:

int int1, int2;
unchecked {
    int1 = int2 = System.Int32.MaxValue;
    int1 += int2;
}
Console.WriteLine (int1); // выведет -2
2013   csharp