6

I'm joining a load of strings to make a superstring but i need to ignore a param if one is null. Currently i cannot think how to do this other than emcompassing all the params in seperate if statements. Help pls:

Here the code

 public void LinkBuilder(string baselink, string sharedkey, string service, string period, string bulletintype,
        string includeresults, string includemap, string username, string password)
    {
        sharedkey = "&" + sharedkey;
        service = "&" + service;
        period = "&" + period;
        bulletintype = "&" + bulletintype;
        includeresults = "&" + includeresults;
        includemap = "&" + includemap;
        username= "&" + username;
        password = "&" + password;

        string completeLink = sharedkey + service + period + bulletintype + includeresults + includemap + username +
                              password;

Not sure how to tackle this.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
marwaha.ks
  • 540
  • 1
  • 7
  • 19

5 Answers5

21

I would really refactor it this way:

public void LinkBuilder(params string[] links)
{
    string completeLink = String.Join("&", links.Where(x=>!String.IsNullOrEmpty(x)));
}
Maksim Simkin
  • 9,561
  • 4
  • 36
  • 49
  • 4
    Possibly make it a `params` parameter, so the caller doesn't even need to create the array... – Jon Skeet Sep 17 '15 at 13:37
  • 1
    for easy use you could add the params keyword public void LinkBuilder(params string[] links) (http://stackoverflow.com/questions/7580277/why-use-the-params-keyword) – fuchs777 Sep 17 '15 at 13:38
  • ok , i think this is the winner, but I would add the params keyword to the method arguments - public void LinkBuilder(params string[] links) - so that the user can still call it with a number of strings separated by commas - LinkBuilder(mybaselink, mysharedkey, myservice...) - but the method accepts them as a string array. –  Sep 17 '15 at 13:40
  • Also the question didn't request that empty strings should be ignored – Stumblor Sep 17 '15 at 13:40
  • @Stumblor - but it seems like that would be assumed unless otherwise stated, if null is ignored, empties also. –  Sep 17 '15 at 13:45
  • You also might want to add an "&" at the beginning of the string, since String.join will only put the separator between the strings, and the OP seemed to want one from the beginning. –  Sep 17 '15 at 13:46
  • @GiliusMaximus would this ensure the strings are in order? – marwaha.ks Sep 17 '15 at 13:50
  • Also sorry to be such a noob, how would i call the LinkBuilder method? LinkBuilder(string baselink, string sharedkey, string service) and it will automatically put the passed param in the array? – marwaha.ks Sep 17 '15 at 13:52
  • the same as you did it before – Maksim Simkin Sep 17 '15 at 13:53
  • @Kam - yes, the "where" LINQ operation preserves order. See http://stackoverflow.com/a/204777/4843530 –  Sep 17 '15 at 13:57
  • It worked - this was my output. "http: //xx.aspx?&x&x&x&x&x&x&x&x" which is exactly what I wanted. Thanks guys – marwaha.ks Sep 17 '15 at 14:07
  • @Kam Seems like a problem, I mean you have `?&x` you have a giant key with no value, and you the `?&` doesn't seem value. – Greg Sep 17 '15 at 14:15
  • @Greg Nope it works, I have replaced the values. the base link is "...blah.aspx?" – marwaha.ks Sep 17 '15 at 15:46
1

You can do a check of strings by operator ?: in method.

public void LinkBuilder(string baselink, string sharedkey, string service, string period, string bulletintype,
        string includeresults, string includemap, string username, string password)
    {
        sharedkey = checkValue(sharedkey);
        service = checkValue(service );
        period = checkValue(period );
        bulletintype = checkValue(bulletintype );
        includeresults = checkValue(includeresults );
        includemap = checkValue(includemap );
        username= checkValue(username );
        password = checkValue(password );

        string completeLink = sharedkey + service + period + bulletintype + includeresults + includemap + username +
                              password;
}
private String checkValue(String str)
{
    return str != null ? "&" + str : "";
}
dremerDT
  • 96
  • 3
  • 11
1

Make an enumerable collection of your strings, use a bit of linq to filter out the nulls, then join it all back together again with String.Join:

var elements = 
    new[]{baselink, sharedkey, service, period, 
          bulletintype, includeresults, includemap, 
          username, password};
var nonNullElements = elements.Where(e => e != null);
var outputString = String.Join("&", nonNullElements);

On the off-chance that you're actually trying to assemble a querystring, there are better ways.

For instance, you could leverage HttpUtility and reflection using the following method for parsing an anonymous object to a query string:

public static class ObjEx
{
    public static string ToQueryString(this object data)
    {
        var collection = data.GetType()
            .GetProperties()
            .Aggregate(
                HttpUtility.ParseQueryString(string.Empty),
                (prev,curr) => {
                    var val = curr.GetValue(data);
                    var propName = curr.Name;
                    prev.Add(propName,val.ToString());
                    return prev;
            });
        return collection.ToString();
    }
}

then

var data = new{foo = "bar", num = 1, cat = "bad", dog = "good", needsEscaping = "é\"&"};
Console.WriteLine(data.ToQueryString());

will give you:

foo=bar&num=1&cat=bad&dog=good&needsEscaping=%u00e9%22%26
spender
  • 117,338
  • 33
  • 229
  • 351
1

If the objective is to avoid wrapping each parameter in an if statement, you could add them to a list, then use String.Join, and Linq.Select

        public void LinkBuilder(string baselink, string sharedkey, string service, string period, string bulletintype,
            string includeresults, string includemap, string username, string password)
    {
        var allParams = new List<string>
        {
            baselink,
            sharedkey,
            service,
            period,
            bulletintype,
            includeresults,
            includemap,
            username,
            password
        };

        var completeLink = "?" + String.Join("&", allParams.Select(p => p != null));
    }
Stumblor
  • 1,118
  • 8
  • 16
1

Below would accept a Collection which I feel may be better maintainable. I re factored a bit.

public string LinkBuilder(Dictionary<string, string> parameters)
{
     var url = String.Empty;
     foreach(var parameter in parameters)
         if(!string.IsNullOrEmpty(parameter.Value))
               url += String.Format("&{0}={1}", parameter.Key, parameter.Value);

     return url;
}

This way you would pass a collection to build your URL, then it would return the giant URL for you. You have a massive selection, I personally like Maksim's answer.

Greg
  • 11,302
  • 2
  • 48
  • 79