По существу, какой бы ни делает код более простым. Единственная точка выхода является хорошим идеалом, но я не изогнул бы код, не в форме только для достижения его... И если альтернатива объявляет локальную переменную (вне блокировки), инициализируя его (в блокировке) и затем возвращает ее (вне блокировки), затем я сказал бы, что простое "нечто возврата" в блокировке намного более просто.
Для показа различия в IL, позволяет коду:
static class Program
{
static void Main() { }
static readonly object sync = new object();
static int GetValue() { return 5; }
static int ReturnInside()
{
lock (sync)
{
return GetValue();
}
}
static int ReturnOutside()
{
int val;
lock (sync)
{
val = GetValue();
}
return val;
}
}
(обратите внимание, что я счастливо обсудил бы это ReturnInside
более простой/более чистый бит C#),
И посмотрите на IL (режим выпуска и т.д.):
.method private hidebysig static int32 ReturnInside() cil managed
{
.maxstack 2
.locals init (
[0] int32 CS$1$0000,
[1] object CS$2$0001)
L_0000: ldsfld object Program::sync
L_0005: dup
L_0006: stloc.1
L_0007: call void [mscorlib]System.Threading.Monitor::Enter(object)
L_000c: call int32 Program::GetValue()
L_0011: stloc.0
L_0012: leave.s L_001b
L_0014: ldloc.1
L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object)
L_001a: endfinally
L_001b: ldloc.0
L_001c: ret
.try L_000c to L_0014 finally handler L_0014 to L_001b
}
method private hidebysig static int32 ReturnOutside() cil managed
{
.maxstack 2
.locals init (
[0] int32 val,
[1] object CS$2$0000)
L_0000: ldsfld object Program::sync
L_0005: dup
L_0006: stloc.1
L_0007: call void [mscorlib]System.Threading.Monitor::Enter(object)
L_000c: call int32 Program::GetValue()
L_0011: stloc.0
L_0012: leave.s L_001b
L_0014: ldloc.1
L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object)
L_001a: endfinally
L_001b: ldloc.0
L_001c: ret
.try L_000c to L_0014 finally handler L_0014 to L_001b
}
Таким образом на уровне IL они - [плюс-минус некоторые имена] идентичный (я изучил что-то;-p). По сути, единственное разумное сравнение является (очень субъективным) законом локального стиля кодирования... Я предпочитаю ReturnInside
для простоты, но я не пришел бы в восторг от также.
использование группы по идентификатору пользователя по отношению к таблице hits_table позволяет получить дату обращения max () для каждого идентификатора пользователя. Я назвал это ПОСЛЕДНИЕ ХИТЫ в приведенном ниже коде.
Выбор в ТАБЛИЦЕ ПОЛЬЗОВАТЕЛЕЙ с левым присоединением к ПОСЛЕДНИМ ХИТАМ позволяет получать записи для каждого пользователя.
присоединяясь обратно к ТАБЛИЦЕ ХИТОВ, вы можете вытащить запись браузера, связанную с этой датой, или пустое значение для пользователей, в которых нет записи.
select
user_table.userid,
user_table.username,
isnull(hitstable.browser, 'unknown') as browser
from
user_table
left join
(
select
userid,
max(hitsdate) hitsdate
from
hits_table
group by
userid
) latest_hits
on
user_table.userid = latest_hits.userid
left join
hits_table
on hits.table.userid = latest_hits.userid
and hits_table.hitsdate = latest_hits.hitsdate
Не могли бы вы выбрать подвыборку, не красиво, но должно работать ..
SELECT U.*,
ISNULL((SELECT TOP 1 BROWSER
FROM HITS_TABLE
WHERE HITS_TABLE.USERID = U.USERID
ORDER BY HITS_TABLE.HITSDATE DESC),'UnKnown') AS Browser
FROM USER_TABLE U
SELECT U.*,'BROWSER' =
case
when (SELECT TOP 1 BROWSER FROM HITS_TABLE WHERE HITS_TABLE.USERID = U.USERID ORDER BY HITS_TABLE.HITSDATE DESC) is null then 'Unknown'
else (SELECT TOP 1 BROWSER FROM HITS_TABLE WHERE HITS_TABLE.USERID = U.USERID ORDER BY HITS_TABLE.HITSDATE DESC)
end
FROM USER_TABLE U