2016-12-09 5 views
0

Возможно ли отлировать Lazy<T>экземпляр как Lazy<object>, когда все, что у меня есть, есть ссылка на объект? Это возвращает нуль:Lazy <T> как Lazy <object> возможно?

var result = obj as Lazy<object>; 

Это имеет смысл для меня. Он должен быть нулевым, потому что его не Lazy<object>. Но есть ли другой способ опросить, чтобы узнать, что на самом деле есть или наложить на объект? Мне на самом деле все равно, что Т на самом деле в этом случае. Мне просто нужна ссылка .Value.

Некоторые фон

Так что это действительно раритет вопрос. Он может применяться к любому объекту, определяющему общий (то есть List<T>). Но вот конкретный случай:
Я придерживаюсь провайдера Lazy<T> в кеше. Я знаю, что такое T, когда я его вставляю, и я знаю, что T в нормальном использовании, когда я вытаскиваю его. Однако в одном случае, когда я управляю кешем, я не знаю, что такое T, и на самом деле я не хочу взаимодействовать с ним, кроме как отправить его значение в сериализатор. Я просто обеспокоен тем, что у меня отсутствует какой-то очевидный способ достичь этого, не создавая способ отслеживать его раньше времени или менять кучу сигнатур/вызовов методов.

ответ

1

Это то, что dynamic ключевое слово для , Он использует одно и то же решение для отражения под ответом @ SledgeHammer, за исключением того, что у него есть кеш для делегатов getter, поэтому он намного быстрее, если вы делаете это более одного раза для того же T. Это также намного короче и легче читать (и писать).

object result = (obj as dynamic).Value; 
+1

ДА! Это то, что мой мозг продолжал говорить мне, но я продолжал думать, сталкиваясь с теми же проблемами, поэтому я не пытался. Ясно, что я не понимал механику под динамикой, поэтому спасибо за эту информацию. – user2245759

0

Занятия в C# не могут быть ковариантными, так что вам не удастся обработать этот экземпляр объекта как Lazy<object>. Вам нужно будет создать объект Lazy, который просто использует другой Lazy, чтобы определить, какое значение должно быть. Это достаточно просто:

Lazy<T> oldLazy = ComputeOldLazy(); 
Lazy<object> newLazy = new Lazy<object>(() => oldLazy.Value); 
+0

отличный ответ на этот вопрос, который я изначально задал. Отредактировал вопрос, чтобы сделать его более понятным. Я не знаю, что такое T, когда я получаю исходную ссылку. На самом деле я знаю только его ленивое, потому что я его там застрял. У меня просто есть ссылка на объект. – user2245759

+0

@ user2245759 Невозможно изменить свой вопрос в совершенно другой вопрос после получения ответа. Если вы хотите задать другой вопрос, задайте другой вопрос. Кроме того, даже с изменением вашего вопроса, это все еще отвечает на него. Этот код не волнует, что такое 'T'. – Servy

+0

@Servy: Почему в мире ты бы сказал такое? Во-первых, это не совсем другой вопрос *. Во-вторых, не могли бы вы предоставить ссылку на закон, который санкционирует такой вид редактирования OP? Ваш ответ неверен просто потому, что для ссылки не существует 'T'. – Leandro

1

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

Lazy<int> l = new Lazy<int>(() => 5); 

    object o = l; 

    object val = o.GetType().GetProperty("Value").GetGetMethod().Invoke(o, null); 
+0

Я действительно не думаю, что есть необходимость проверить с помощью 'HasValue' (и не существует такого свойства). Вы имели в виду 'IsValueCreated'? В любом случае, цель этого типа - именно то, чтобы допускать ленивую инициализацию. – Leandro

+1

@LeandroTaset - oops ... Я думал, что он недействителен ... Я вынул редактирование. – SledgeHammer