简体   繁体   中英

How can I write this shorter?

public static string GetUa(HttpRequest hr)
{
    try
    {
        string visitorBrowser = hr.UserAgent.ToString();
        string originalBrowser = hr.ServerVariables["X-OperaMini-Phone-UA"];
        string anotherOriginalBrowser = hr.ServerVariables["X-Device-User-Agent"]; //novarra

        if (!String.IsNullOrEmpty(originalBrowser))
        {
            return "OPERAMINI " + originalBrowser;
        }
        else
        {
            if (!String.IsNullOrEmpty(anotherOriginalBrowser))
            {
                return "NOVARRA " + anotherOriginalBrowser;
            }
            else
            {
                return visitorBrowser;
            }
        }
    }
    catch
    {
        return "No UA Found";
    }
}

I'd be more concerned with readability. This seems nicer to me:

var operaAgent = hr.ServerVariables["X-OperaMini-Phone-UA"];
var deviceAgent = hr.ServerVariables["X-Device-User-Agent"];

operaAgent = string.IsNullOrEmpty(operaAgent) ? null : "OPERAMINI" + operaAgent;
deviceAgent = string.IsNullOrEmpty(deviceAgent) ? null : "NOVARRA" + deviceAgent;

return operaAgent ?? deviceAgent ?? hr.UserAgent ?? "Not Found";

Of course, if you didn't need to prefix those strings onto the UAs and didn't need to concern yourself with empty string user agents, then it would simply be:

return hr.ServerVariables["X-OperaMini-Phone-UA"] ??
       hr.ServerVariables["X-Device-User-Agent"] ??
       hr.UserAgent ??
       "Not Found";

I don't see any way to significantly shorten that.

One way to save a few lines is to get rid of the braces around the first else:

if (!String.IsNullOrEmpty(originalBrowser))
{
    return "OPERAMINI " + originalBrowser;
}
else if (!String.IsNullOrEmpty(anotherOriginalBrowser))
{
    return "NOVARRA " + anotherOriginalBrowser;
}
else if (!String.IsNullOrEmpty(visitorBrowser))
{
    return visitorBrowser;
}
else
{
    return "No User Agent Detected";
}

You should be careful about using exceptions for flow control, too. statenjason has the right idea.

Right now, what you have is clear and legible. If you're trying to get there with less processing time, I don't think you're going to make it. If you're trying to get there with fewer lines of code, you can, but it's going to be ugly.

One easy way to shorten it on-screen (same LOC count, -1) is to remove some of your curly braces and not store visitorBrowser :

public static string GetUa(HttpRequest hr)
{
    try
    {
        string originalBrowser = hr.ServerVariables["X-OperaMini-Phone-UA"];
        string anotherOriginalBrowser = hr.ServerVariables["X-Device-User-Agent"]; //novarra

        if (!String.IsNullOrEmpty(originalBrowser))
            return "OPERAMINI " + originalBrowser;
        else
            if (!String.IsNullOrEmpty(anotherOriginalBrowser))
                return "NOVARRA " + anotherOriginalBrowser;
            else
                return hr.UserAgent.ToString();
    }
    catch
    {
        return "No UA Found";
    }
}

To me, this is slightly less readable, but probably still livable.

Now you can make it really short by using the conditional operator ( ?: ), but it's going to also be really nasty for readability. If I saw code like the following in a code review, I'd make the developer rewrite it for clarity:

public static string GetUa(HttpRequest hr)
{
    try
    {
        string visitorBrowser = hr.UserAgent.ToString();
        string originalBrowser = hr.ServerVariables["X-OperaMini-Phone-UA"];
        string anotherOriginalBrowser = hr.ServerVariables["X-Device-User-Agent"]; //novarra

        return !(string.IsNullOrEmpty(originalBrowser)) ? "OPERAMINI " + originalBrowser :
               !(string.IsNullOrEmpty(anotherOriginalBrowser)) ? "NOVARRA " + anotherOriginalBrowser : visitorBrowser);
    }
    catch 
    {
        return "No UA Found";
    }
}

Seriously, please don't do the second example. (I'm not 100% sure that will compile; I'm writing it off the top of my head on my Mac at the moment. But I'm 99.9% sure it will, and will work, and the next developer will HATE you for it.)

Like this, for example:

public static string GetUa(HttpRequest hr) {
  try {
    string originalBrowser = hr.ServerVariables["X-OperaMini-Phone-UA"];
    string anotherOriginalBrowser = hr.ServerVariables["X-Device-User-Agent"];
    return
      !String.IsNullOrEmpty(originalBrowser) ? "OPERAMINI " + originalBrowser :
      !String.IsNullOrEmpty(anotherOriginalBrowser) ? "NOVARRA " + anotherOriginalBrowser :
      hr.UserAgent;
  } catch {
    return "No UA Found";
  }
}

Like this (everything else is just extra code doing nothing):

public static string GetUa(HttpRequest hr) 
{ 
    if (!String.IsNullOrEmpty(hr.ServerVariables["X-OperaMini-Phone-UA"])) 
        return "OPERAMINI " + hr.ServerVariables["X-OperaMini-Phone-UA"])) ; 
    if (!String.IsNullOrEmpty(hr.ServerVariables["X-Device-User-Agent"])) 
        return "NOVARRA " +   hr.ServerVariables["X-Device-User-Agent"])) ; 
    return hr.UserAgent ?? "Not Found"; 
} 

And you should NEVER use exceptions in your normal application flow path.

Here's a condensed version. Because you're return ing inside each if statement, you can eliminate your else s. Also, I eliminated the need for using exceptions for flow.

    public static string GetUa(HttpRequest hr)
    {
        string visitorBrowser = hr.UserAgent;
        string originalBrowser = hr.ServerVariables["X-OperaMini-Phone-UA"];
        string anotherOriginalBrowser = hr.ServerVariables["X-Device-User-Agent"]; //novarra
        if (string.IsNullOrEmpty(visitorBrowser))
            return "No UA Found";
        if (!String.IsNullOrEmpty(originalBrowser))
            return "OPERAMINI " + originalBrowser;
        if (!String.IsNullOrEmpty(anotherOriginalBrowser))
            return "NOVARRA " + anotherOriginalBrowser;
        return visitorBrowser;
    }
public static string GetUa(HttpRequest hr)
{
    try
    {
        string visitorBrowser = hr.UserAgent.ToString();
        string originalBrowser = hr.ServerVariables["X-OperaMini-Phone-UA"];
        if (!String.IsNullOrEmpty(originalBrowser)) return "OPERAMINI"+originalBrowser;
        string anotherOriginalBrowser = hr.ServerVariables["X-Device-User-Agent"]; //novarra
        if (!String.IsNullOrEmpty(anotherOriginalBrowser)) return "NOVARRA" + anotherOriginalBrowser;
        return visitorBrowser;
    }
    catch
    {
        return "No UA Found";
    }
}

second if-statment:

return (!String.IsNullOrEmpty(anotherOriginalBrowser) ? ("NOVARRA " + anotherOriginalBrowser) : visitorBrowser);

You can probably use this combined with the first if-statment too

I don't like when it is doing work that it doesn't have to do. So I would write it as follows:

   public static string GetUa(HttpRequest hr)
    {
        string browser = hr.ServerVariables["X-OperaMini-Phone-UA"];
        if (!String.IsNullOrEmpty(browser))
            return "OPERAMINI " + browser;

        browser = hr.ServerVariables["X-Device-User-Agent"]; //novarra 
        if (!String.IsNullOrEmpty(browser))
            return "NOVARRA " + browser;

        if (!String.IsNullOrEmpty(hr.UserAgent))
            return hr.UserAgent;

        return "No UA Found";
    } 

A slightly more dynamic .NET 4 approach:

    private static readonly Tuple<string, string>[] SpecialUas =
        {
            Tuple.Create("X-OperaMini-Phone-UA", "NOVARRA"),
            Tuple.Create("X-Device-User-Agent", "OPERAMINI")
        };

    public static string GetUa(HttpRequest r)
    {
        return (
                   from specialUa in SpecialUas
                   let serverVariable = r.ServerVariables[specialUa.Item1]
                   where !string.IsNullOrEmpty(serverVariable)
                   select string.Concat(specialUa.Item2, " ", serverVariable)
               ).FirstOrDefault() ?? (
                   string.IsNullOrEmpty(r.UserAgent)
                   ? "No UA Found"
                   : r.UserAgent
               );
    }

This can be customised with additional special UAs very easily by adding further tuples.

It wouldn't be difficult to replace the tuples with something else if you're not running on .NET 4.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM