How could I improve this code?
var to = "http://forum.";
if (!RedirectPermanent("http://www.", to))
if (!RedirectPermanent("http://blog.", to))
if (!RedirectPermanent("http://forum.", to))
if (!RedirectPermanent("http://tracker.", to))
if (!RedirectPermanent("http://wiki.", to))
RedirectPermanent("http://", to);
This is the method:
private bool RedirectPermanent(string from,string to)
{
if (Request.Url.AbsoluteUri.StartsWith(from))
{
var domain = Request.Url.GetLeftPart(UriPartial.Authority).Replace(from, to);
Response.RedirectPermanent(string.Concat(domain, Request.RawUrl));
return true;
}
return false;
}
3 Answers 3
Went for this:
var arr = new[] { "http://www.", "http://blog.", "http://forum.", "http://tracker.", "http://wiki.", "http://" };
var to = "http://forum.";
foreach (var from in arr)
{
if (RedirectPermanent(from, to))
break;
}
-
4\$\begingroup\$ Slight criticism, use better variable names. Expand it to
redirectSources
,redirectTo
andredirectFrom
. And in general, don't use contextual keywords as variable names such asfrom
, even though safe, you should treat it like any other keywords and avoid it all together. \$\endgroup\$Jeff Mercado– Jeff Mercado2011年08月14日 23:20:21 +00:00Commented Aug 14, 2011 at 23:20
Review
- That level of nesting hurts readability.
- There is a lack of re-usability for a common set of source urls to redirect.
- You have specified an ultimate fallback of
http://
. But what if we encounterhttps://
orftp://
?
Alternative
As suggested by others, you want to loop a collection of input values and break on first match. The way I would do it is to provide a utility method. Use a HashSet
to avoid duplicates.
private bool RedirectPermanent(HashSet<string> redirectSources, string redirectTo)
{
return redirectSources.Any(x => RedirectPermanent(x, redirectTo));
}
As a variation:
var arr = new[] { "http://www.", "http://blog.", "http://forum.", "http://tracker.", "http://wiki.", "http://" };
var to = "http://forum.";
int i = 0;
while ((!RedirectPermanent(from[i], to)) && i < arr.Length)
{
++i; // reversed from i++
if (i > arr.length) { break; }
}
There are several reasons I prefer this over a foreach
:
foreach
has a performance cost to execute. An internal state machine iterator has to be instantiated. Thewhile
with a count limiter essentially does the same thing. While this is a performance tweak, IMO, it's still a better practice.code is not restricted/limited by the locked state of the iterated collection or the state machine iterator.
IMO, using
foreach
with a body ofif-then-break
smells and reads like slang rather than proper grammar. ;)
-
\$\begingroup\$ This may have been different 8 years ago, but nowadays a
foreach
loop over an array produces IL bytecode that is quite similar to that for afor
orwhile
loop - in this case aforeach
loop is even slightly faster. More importantly, it's less error-prone: your loop fails with anIndexOutOfRangeException
if none of the redirects is successful. \$\endgroup\$Pieter Witvoet– Pieter Witvoet2019年07月10日 22:24:07 +00:00Commented Jul 10, 2019 at 22:24 -
\$\begingroup\$ A
foreach
loop does use an enumerator for other collection types, and that might be a bit slower. On the other hand, it works with any type that has an appropriateGetEnumerator
method, it's easy to get right, and the intent is clear. The restrictions you mention are not inherent toforeach
, they're an intentional safety mechanism in the enumerators of most BCL collection types. \$\endgroup\$Pieter Witvoet– Pieter Witvoet2019年07月11日 06:55:36 +00:00Commented Jul 11, 2019 at 6:55 -
1\$\begingroup\$ Fair enough; I was only somewhat aware that optimizations had occurred in compiling
foreach
(and other loop/enumerator ops). As far as restrictions go, regardless of the purpose - safety, whatever - they are still restrictions and I agree with the need for safeguards. Added check for 'out of range'. \$\endgroup\$IAbstract– IAbstract2019年07月13日 15:47:19 +00:00Commented Jul 13, 2019 at 15:47 -
\$\begingroup\$ Your new out-of-range check is also broken... \$\endgroup\$Pieter Witvoet– Pieter Witvoet2019年07月13日 23:28:20 +00:00Commented Jul 13, 2019 at 23:28