Структура С#/таблица поиска

Скажем, у меня есть структура, объявленная следующим образом:

public struct Test
{
    public static int Width = 5;
    ...
    public static int[] Value = new int[1]{ 0 };
}

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

public struct AnotherStruct
{
    public (type of struct) this[int key]
    {
        get
        {
            switch(key)
            {
                case 1:
                    return (another struct);
                default:
                    return null;
            }
        }
    }
}

Моя конечная цель заключается в том, что я хочу использовать код, который выглядит следующим образом, без необходимости создавать экземпляр объекта:

structobject s = new AnotherStruct[5];

Таким образом, эта «таблица поиска» будет создана в другом проекте и построена, а затем вызвана как dll из моего основного проекта. Поскольку я создаю dll в другом месте и вызываю ее, я надеюсь, что смогу загрузить dll в память один раз, а затем я могу просто ссылаться на эту память из моего основного проекта. Тогда у меня будет одна выделенная часть памяти, и мой код будет просто ссылаться на нее, избегая необходимости создавать отдельные экземпляры этой таблицы поиска (таким образом, избегая накладных расходов времени, необходимых для выделения памяти и сохранения нового экземпляра). Время, которое я бы сэкономил, было бы чрезвычайно полезным в долгосрочной перспективе, поэтому я надеюсь, что смогу как-то заставить это работать.

Я надеюсь, что это не слишком запутанно, но дайте мне знать, если необходимы какие-либо разъяснения.

Редактировать Это используется на веб-сайте, поэтому мне действительно нужен объект, который сохраняется при всех подключениях и создается один раз при начальной загрузке кода. Та же идея, но, может быть, это упростит решение?


person JesseBuesking    schedule 08.05.2011    source источник
comment
Похоже, вам нужна заводская выкройка.   -  person Etienne de Martel    schedule 08.05.2011
comment
@Etienne de Martel Не могли бы вы создать краткий пример того, как это будет работать с точки зрения dll и внутри основного проекта. На самом деле ничего особенного. Я никогда раньше не использовал фабричный шаблон, и мои ограниченные исследования показывают, что он довольно сложный.   -  person JesseBuesking    schedule 08.05.2011
comment
Нюанс: структуры являются типами значений, поэтому, чтобы иметь возможность возвращать значение null, вам нужно использовать специальный тип структуры, допускающий значение null, Nullable<Test> или Test?.   -  person BoltClock    schedule 08.05.2011
comment
Я мог бы вернуть что-то отличное от нуля, но спасибо за внимание.   -  person JesseBuesking    schedule 08.05.2011
comment
Странно, что вы думаете, что вам нужен struct, чтобы сохраняться между подключениями и создаваться только один раз. Есть ряд более эффективных способов справиться с этим (создать синглтон, кэшированный на уровне приложения, в Application_Start(..) вашего global.asax.cs. Использование структур для такого общего назначения может быть опасно   -  person Bobby D    schedule 08.05.2011
comment
Это безумие - struct - это тип значения, вы все равно создаете копию, фабрику или нет.   -  person BrokenGlass    schedule 08.05.2011


Ответы (3)


Решение №2. Откажитесь от всей идеи ID и просто используйте тип структуры и дженерики.

public struct St1 
{
}
public struct St2 
{
}

public class Factory<T>
    where T : struct
{
    static T _new = new T(); //cached copy of structure

    public static T New { get { return _new; } }        
}


class Program
{
    static void Main(string[] args)
    {
        St1 x1 = Factory<St1>.New;
        St1 x2 = Factory<St1>.New;
        St1 x3 = Factory<St1>.New;
        St2 y1 = Factory<St2>.New;
        St2 y2 = Factory<St2>.New;
    }
}
person John Alexiou    schedule 08.05.2011

Решение №1. Использование общего интерфейса для всех структур и коллекции словарей

public interface IStr { }

public struct St1 : IStr
{
    public static int ID = 1;
}
public struct St2 : IStr
{
    public static int ID = 2;
}

public class StructFactory : System.Collections.ObjectModel.KeyedCollection<int, IStr>
{
    public static StructFactory Default = new StructFactory();
    protected override int GetKeyForItem(IStr item)
    {
        FieldInfo finfo = item.GetType().GetField("ID", 
            BindingFlags.Static | BindingFlags.Public);

        return (int)finfo.GetValue(item);
    }

    public StructFactory()
    {
        Add(new St1());
        Add(new St2());
    }
}

class Program
{
    static void Main(string[] args)
    {
        St1 x = (St1)StructFactory.Default[1];
        St2 y = (St2)StructFactory.Default[2];
    }
}
person John Alexiou    schedule 08.05.2011

Синтаксис, который вы использовали выше, не будет работать, поскольку он означает «создать массив AnotherStruct с пятью элементами». Однако, как упоминалось в комментарии, вам действительно следует изучить использование фабричного шаблона.

Однако, если вы действительно хотите использовать приведенный выше шаблон, вы можете немного изменить его. Пусть ваш массив AnotherStruct содержит экземпляры Type каждой из ваших структур. Тогда ваша строка «создания» будет выглядеть примерно так:

structobject s = (structobject)Activator.CreateInstance(AnotherStruct[5]);

Вы можете использовать отражение в сборке (поскольку вы оборачиваете ее в DLL), чтобы получить эти объекты Type.

И, наконец, если у вас нет действительно веских причин для использования struct (и вы понимаете все нюансы, которых существует несколько), придерживайтесь class.

person seairth    schedule 08.05.2011