Войти
ФлеймФорумПрограммирование

Интерфейсы в C# 8.0 (6 стр)

Страницы: 1 2 3 4 5 6 7 Следующая »
#75
(Правка: 17:19) 17:18, 6 сен. 2019

Приватных (нестатических) переменных почему-то не завезли, но можно их сэмулировать:

using System;
using System.Collections.Generic;
using System.Linq;

public interface ITest
{
    private static List<(object Key, Container Value)> _instances =
        new List<(object, Container)>();

    private class Container
    {
        public int Value { get; set; }
    }

    int DoIt()
    {
        Container container = _instances
            .Where(item => ReferenceEquals(item.Key, this))
            .FirstOrDefault()
            .Value;

        if (container == null)
        {
            _instances.Add((this, new Container() { Value = 0 }));
            return DoIt();
        }

        return container.Value++;
    }
}

public class ClassTest : ITest { }

public class Program
{
    public static void Main()
    {
        ITest test1 = new ClassTest();
        ITest test2 = new ClassTest();

        for (int i = 0; i < 10; ++i)
        {
            Console.WriteLine(test1.DoIt());
        }

        for (int i = 0; i < 10; ++i)
        {
            Console.WriteLine(test2.DoIt());
        }
    }
}


#76
(Правка: 18:09) 17:53, 6 сен. 2019

Ну а вот так можно унаследовать свой интерфейс от IStateful и создавать в нём любые свойтсва с состоянием:

using System;
using System.Collections.Generic;
using System.Linq;

public interface IStateful
{
    private static Dictionary<string, List<(object Key, object Value)>> _instances =
        new Dictionary<string, List<(object, object)>>();

    protected T GetProperty<T>(string name)
    {
        if (!_instances.ContainsKey(name))
            return default;

        var list = _instances[name];

        var items = list
            .Where(item => ReferenceEquals(item.Key, this));

        if (items.Count() == 0)
            return default;

        return (T)items.First().Value;
    }

    protected void SetProperty<T>(string name, T value)
    {
        if (!_instances.ContainsKey(name))
            _instances.Add(name, new List<(object, object)>());

        _instances[name] = _instances[name].Where(item => !ReferenceEquals(item.Key, this)).ToList();
        _instances[name].Add((this, value));
    }
}

public interface ITest : IStateful
{
    public int Value
    {
        get => GetProperty<int>(nameof(Value));
        set => SetProperty(nameof(Value), value);
    }
}

public class CTest : ITest { }

public class Program
{
    public static void Main()
    {
        ITest test1 = new CTest();
        ITest test2 = new CTest();

        for (int i = 0; i < 5; ++i)
            Console.WriteLine(test1.Value++);

        for (int i = 0; i < 5; ++i)
            Console.WriteLine(test2.Value++);
    }
}
#77
(Правка: 18:58) 18:55, 6 сен. 2019

Нихао
> Ну а вот так можно унаследовать свой интерфейс от IStateful и создавать в нём
> любые свойтсва с состоянием:
брал бы проще:

interface Test
{
   void SetValue(int i);
   int GetValue();
}
и говорил бы, что вот - состояние!
Проблема в том, что "наличие состояния" контролируется конкретной реализацией интерфейса.
Например, в моей реализации интерфейса Test, SetValue() будет игнорироваться, а GetValue() возвращать константу.

Кивать на статические переменные бесполезно, потому что:
1) реализацию метода интерфеса в потомке можно поменять, что статическая переменная не будет использоваться.
2) привязка к статической методу сделана в конкретной реализации; (интерфейс это набор методов, в первую очередь)
3) наличие статических переменных сделана исключительно из-за особенности (убогости!) C#. Т.к. просто объявить глобальную переменную в пространстве имён нельзя, её нужно воткнуть в какой-то класс. И чтобы просто ради переменной класс не объявлять, разрешили теперь статику в интерфейсы.

#78
(Правка: 20:23) 20:22, 6 сен. 2019

slepov
> Событие в интерфейсе - это для начала пара дырок add/remove, что по сути пара
> методов. Говорить что делегаты дают какое то состояние - ну тогда и методы
> состояние. Тогда вообще все есть состояние, приехали.

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

Спорить тут можно лишь о субъективном восприятии, откуда взялось состояние: пришло из интерфейса или возникло внутри реализующего его типа. Если считать, что возникло внутри типа, то можно в интерфейсы и поля добавлять, и всё что хочешь ― это ничему не противоречит, ничего не нарушает, ничего не меняет.

#79
(Правка: 20:39) 20:38, 6 сен. 2019

Нихао
> Приватных (нестатических) переменных почему-то не завезли, но можно их
> сэмулировать:
> private static List<(object Key, Container Value)> _instances = new List<(object, Container)>();

Будет утечка памяти. Ссылки на объекты Key будут храниться в этой коллекции вечно, сборщик мусора не сможет удалять ни сами объекты, ни ассоциированные с ними значения. Проблему решает ConditionalWeakTable<TKey,TValue> ― ровно для этого придумана.

#80
20:44, 6 сен. 2019

alexzzzz
> это ничему не противоречит, ничего не нарушает, ничего не меняет
Так и придумали C++. Там вообще ничего ничему не противоречит, хоть указатели сдвигай и через void* читай. Просто мелкомягкие с таким пафосом задвигали про "безопасность", "простоту" и "понятность", а теперь всё больше фичей из плюсов вводят, маскируя их стеной текста, якобы это что-то другое (яркий пример - делегаты, которые "совсем не указатели на функции", а [и дальше пошли 2 страницы описания того, как работают указатели на функции]).
Ещё через пару лет мы увидим множественное наследование с полями, которое "вовсе не множественное наследование с полями"... А, нет, не угадал, не через пару лет, оно уже есть.

#81
21:03, 6 сен. 2019

pahaa
Ну если сделать как в C++ то где то в индии начнутся массовые расстрелы, а бизнес от этого потеряет ведь ему обещали что в .NET больше никаких указателей, память больше не ресурс и интерфейсы в которые нельзя насрать.
А в реальности var, dynamic, Dispose, Finalize, GC.SuppressFinalize, GC.Collect, осталось только в C# добавить void* и reinterpret_cast

#82
(Правка: 21:08) 21:08, 6 сен. 2019

gamedevfor
> осталось только в C# добавить void* ...
fixed?

#83
21:17, 6 сен. 2019

skalogryz
Не совсем то что надо.

void* - это сила:

int[] arr = { 0, 1, 2, 3, 4, 5 };
fixed (void* ptr = arr) 
{ 
   int* int_ptr = ptr;
   char* char_ptr = ptr;
}

#84
(Правка: 22:17) 22:13, 6 сен. 2019

gamedevfor
> Не совсем то что надо.
по-моему, именно то!
работает идеально

using System;

public class Test
{
  unsafe public static void Main()
  {
    // your code goes here
    int[] arr = { 0, 1, 2, 3, 4, 5 };
    Console.WriteLine(arr[0]);
    fixed (void* ptr = arr) 
    { 
      int* int_ptr = (int *)ptr;
      char* char_ptr = (char *)ptr;
      *char_ptr = 'a'; char_ptr++;
      *char_ptr = 'b'; char_ptr++;
      *char_ptr = 'c'; char_ptr++;
      *char_ptr = 'd'; char_ptr++;
    }
    Console.WriteLine(arr[0]);
  }
}
выхлоп:
0
6422625
можно изобретать что угодно и как угодно, НО главное чтобы были void* и goto!


пруф:
alexzzzz
> У меня больше утилитарный подход: данная фича удобна/полезна в данном месте ―
> использую, нет ― не использую. Могу не моргнув написать goto

#85
22:19, 6 сен. 2019

skalogryz
> unsafe

вообще то индусам хотелось бы void* без unsafe )))

#86
(Правка: 22:40) 22:33, 6 сен. 2019

gamedevfor
> вообще то индусам хотелось бы void* без unsafe )))


можно изобретать что угодно и как угодно, НО главное чтобы были препроцессор, void* и goto!

#DEFINE absolutely_safe         unsafe
#DEFINE i_know_what_i_am_doing  unsafe
#DEFINE we_have_deadlines       unsafe

#87
22:54, 6 сен. 2019

skalogryz
gosub еще не помешал бы.

#88
15:57, 8 сен. 2019

skalogryz
>> Это называется подорвались на своей же мине. )))
> не совсем.
> новые интерфейсы не добавили ни полей в интерфейсы (есть свойства, которые доступны через методы), ни конструкторов.
> добавили методы по-умолчанию, ну как бы тоже на реализацию влияет косвенно.
Ну я тебе показал, как добавить состояние. Потому не вижу причин, почему его не добавили разработчики языка. Ну а конструкторы тогда уж очень напрашиваются. И интерфейсы превращаются в абстрактные классы.

#89
(Правка: 16:45) 16:24, 8 сен. 2019

Указатели/unsafe ― это удобно и полезно, но и без них прикольно.

using System;
using System.Runtime.InteropServices;

public class Test
{
    [StructLayout(LayoutKind.Explicit)]
    private struct Union
    {
        public class FakeArray { public int length; }

        [FieldOffset(0)] public int[] ints;
        [FieldOffset(0)] public char[] chars;
        [FieldOffset(0)] public FakeArray fake;
    }

    public static void Main()
    {
        int[] arr = { 0, 1, 2, 3, 4, 5 };
        Console.WriteLine(arr[0]);

        var union = new Union {ints = arr};
        union.chars[0] = 'a';
        union.chars[1] = 'b';
        Console.WriteLine(arr[0]);

        union.fake.length = -42;
        Console.WriteLine(arr.Length);
    }
}
0
6422625
-42
Press any key to continue . . .

:)

Страницы: 1 2 3 4 5 6 7 Следующая »
ФлеймФорумПрограммирование