ссылочные объекты в дженериках c # - PullRequest
1 голос
/ 07 марта 2012

Как я могу использовать ref универсального класса в качестве параметра и изменить данные.Вот мой пример кода

bool IRequestHandler.ParseRequest<T>(string request, ref T obj)
{
    var req = RequestHandlerGateway.DeserializeFromXml<OrderMessageSalesOrder>(request, "SalesOrder");

    return false;
}

Я хочу обновить данные внутри obj.

Ответы [ 4 ]

1 голос
/ 07 марта 2012

Вы мало что можете сделать с "T obj", если не сообщите компилятору, какие дополнительные интерфейсы он поддерживает.

* 1003 Е.Г. *

IRequestHandler.ParseRequest<T>(string request, T obj)
where T : IOrderInfo
{
    var req = RequestHandlerGateway.DeserializeFromXml<OrderMessageSalesOrder>(request, "SalesOrder");
    obj.OrderId = req.Id;
    return true;
}

Предполагая, что IOrderInfo определяет свойство OrderId, а OrderMessageSalesOrder предоставляет свойство Id (или поле).

Ссылка необходима только в том случае, если вы намереваетесь создать новый экземпляр T:

IRequestHandler.ParseRequest<T>(string request, ref T obj)
where T : IOrderInfo, new()
{
    var req = RequestHandlerGateway.DeserializeFromXml<OrderMessageSalesOrder>(request, "SalesOrder");
    obj = new T();
    obj.OrderId = req.Id;
    return true;
}

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

0 голосов
/ 07 марта 2012

Ссылка часто используется для вводимых значений. Если ваш параметр obj относится к ссылочным типам (поскольку вы называете его «obj»), нет необходимости добавлять ключевое слово ref. Чтобы изменить значение объекта, вам нужно дать ему тип. Одним из способов является использование преобразования типа, например:

MyTyped myObj = (MyTyped)obj;

И установка значений для myObj также изменит значения для obj (потому что это ссылка).

Также, если вы можете найти базовый класс / интерфейс для obj, просто измените свой код на:

bool IRequestHandler.ParseRequest<BaseClass>(string request, BaseClass obj)
0 голосов
/ 07 марта 2012

Вам не нужно использовать ключевое слово ref, если вы имеете дело с классами, а не со структурами, поскольку они все равно всегда передаются по ссылке.Возможно, вы захотите использовать ключевое слово out вместо этого, пару изменений улучшат его.

bool IRequestHandler.ParseRequest<T>(string request, out T obj)
{
    try
    {
        var req = RequestHandlerGateway.DeserializeFromXml<T>(request, "SalesOrder");
        obj = req;
        return true;
    }
    catch
    {
        obj = default(T);
        return false;
    }
}

Таким образом, вы можете затем назвать его следующим образом:

OrderMessageSalesOrder salesOrder;

if(handler.ParseRequest(request, out salesOrder))
{
    // parsed successfully, salesOrder will be an instance populated with the data in the request.
}
else
{
    // unable to parse, salesOrder will be null.
}
0 голосов
/ 07 марта 2012

Вы можете привести результат вашей десериализации к объекту, затем привести его к T, но убедитесь, что объект, который вы получаете от вашего метода DeserializeFromXML, имеет тип T

bool IRequestHandler.ParseRequest<T>(string request, ref T obj)
{
    var req = RequestHandlerGateway.DeserializeFromXml<OrderMessageSalesOrder>(request, "SalesOrder");

    obj = (T)(object)(req);    // Careful here

    return false;
}

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

...