2016-05-28 2 views
0

У меня есть два списка объектаКак назначить ссылочный объект

[Serializable] 
private class MemorySet 
{ 
    public Dictionary<string, object> _Map; 
    public List<object> _Results; 
    public List<object> _Storage; 
} 
MemorySet Memory = new MemorySet(); 

я могу иметь ключи, назначенные для объекта, например

_Map.Add("someKey", _Results[_Results.Count - 1]); 

У меня есть метод

private object Mapper(string key) 
{ 
    if (Memory._Map.ContainsKey(key)) 
    { 
     return Memory._Map[key]; 
    } 
    else if (key.ToLower() == "result") 
    { 
     return Memory._Results[Memory._Results.Count - 1]; 
    } 
    else if (key.ToLower() == "storage") 
    { 
     return Memory._Storage[Memory._Storage.Count - 1]; 
    } 
    else if (key.ToLower().Contains("result")) 
    { 
     int n = Convert.ToInt32(key.ToLower().Split(new string[] { "result" }, StringSplitOptions.None)[1]); 
     return Memory._Results[n]; 
    } 
    else if (key.ToLower().Contains("storage")) 
    { 
     int n = Convert.ToInt32(key.ToLower().Split(new string[] { "storage" }, StringSplitOptions.None)[1]); 
     return Memory._Storage[n]; 
    } 
    else return null; 
} 

Теперь я должен назначить объект из _Storage или _Результаты вроде этого:

object obj = key != "" ? Mapper(key) : Memory._Storage[Memory._Storage.Count - 1]; 
if(obj is string) obj as string = "test"; 

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

Другими словами, obj станет «тестом», но базовый объект не будет изменен.

Я понимаю, почему это происходит, хотя я и не думал об этом, когда писал весь двигатель, и теперь у меня большие проблемы с этим. В C++ у нас есть указатели, но в C# я не хочу использовать GCHandles или неуправляемый код для этого тривиального материала, будет крайне уродливым.

Итак, как назначить объекту, на который указывает объект, вместо этого присваивается самому объекту?

+0

Я не знаю точно, что вы пытаетесь сделать здесь, но я скажу вам, что вы» re correct: указатели на указатели на C# не удобны. Тем не менее, я знаю, что это мало значит, но я никогда не сталкивался с этой проблемой раньше. Я бы, наверное, сделал шаг назад и поставил вопрос, правильно ли это решение в первую очередь. Это кажется сложным и подверженным ошибкам, но это только мое мнение. Возможно, для того, чтобы эти разнообразные операции были введены в один нечетко типизированный метод, это не лучший способ сделать это. –

+0

Ну, в нескольких словах у меня есть методы, которые назначают здесь или там, и мне нужен метод, который сообщает, где назначить на основе некоторых критериев. Проблема в том, что я не могу передавать такие объекты – JDE

+0

Ваше соглашение об именах довольно нестандартно.Обычно публичные свойства или поля начинаются с заглавной буквы. Частные свойства или поля начинаются с символа подчеркивания, а затем строчной буквы. Это не большое дело, а просто похоже на то, что вы, возможно, не знаете. – bodangly

ответ

0

Попробуйте

[Serializable] 
    private class MemorySet 
    { 
     public Dictionary<string, object> _Map = new Dictionary<string,object>(); 
     public List<object> _Results = new List<object>(); 
     public List<object> _Storage = new List<object>)_; 
    } 
+0

Что это значит? – JDE

+0

Перед добавлением данных словарь и список <> должны вызвать конструктор (с новым). Вы пытаетесь добавить данные перед вызовом конструктора. – jdweng

+0

Я делаю это где-то в другом месте, но это должно было бы дать нулевую ссылку, было бы очевидно, не так ли? – JDE

0

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

private void Update(string key, object value) 
{ 
    if (Memory._Map.ContainsKey(key)) 
    { 
    Memory._Map[key] = value; 
    } 
    else if (key.ToLower() == "result") 
    { 
    Memory._Results[Memory._Results.Count - 1] = value; 
    } 
    else if (key.ToLower() == "storage") 
    { 
    Memory._Storage[Memory._Storage.Count - 1] = value; 
    } 
    else if (key.ToLower().Contains("result")) 
    { 
    int n = Convert.ToInt32(key.ToLower().Split(new string[] { "result" }, StringSplitOptions.None)[1]); 
    Memory._Results[n] = value; 
    } 
    else if (key.ToLower().Contains("storage")) 
    { 
    int n = Convert.ToInt32(key.ToLower().Split(new string[] { "storage" }, StringSplitOptions.None)[1]); 
    Memory._Storage[n] = value; 
    } 
    else 
    { 
    throw new ArgumentException("Failed to compute valid mapping", nameof(key)); 
    } 
} 

Может быть, вы могли бы также добавить key == "" картину там, я не уверен, чтобы понять, как это будет использоваться точно, но, надеюсь, вы поняли идею.

EDIT: ОК, поэтому ссылки на один и тот же объект используются в разных структурах. Вы должны рассмотреть возможность создания MemorySet, который позволяет избежать этого. Если вы все еще считаете, что это правильный дизайн, учитывая ваши потребности, у вас есть простое решение: оберните целевые объекты в другие объекты.

public class ObjectWrapper 
{ 
    public object ObjectOfInterest { get; set; } 
} 

Теперь вы храните ObjectWrapper объектов. После этого вы можете обновить свойство ObjectOfInterest и это изменение будет отражено во всех структурах, которые содержат этот ObjectWrapper:

ObjectWrapper wrapper = Mapper(key); 
wrapper.ObjectOfInterest = "test"; 
+0

Это не сработает, потому что Memory._Map [key] = значение; будет устанавливать соответствующий объект в словаре, а не тот, который находится в списке – JDE

+0

@JDE. Достаточно справедливо, см. мой обновленный ответ. –

Смежные вопросы