Question: I want to eliminate some duplicated code. Can anyone make this code shorter and better?

```
switch (now.site)
{

    case item.SITE.AMAZON:
        try
        {
            price = driver.FindElement(By.XPath("//*[@id=\"priceblock_ourprice\"]")).Text;
            fetched = true;
        }
        catch
        {
            try
            {
                price = driver.FindElement(By.XPath("//*[@id=\"priceblock_dealprice\"]")).Text;
                fetched = true;
            }
            catch
            {
                fetched = false;
            }
        }
        break;
    case item.SITE.ALI:
        try
        {
            price = driver.FindElement(By.XPath("//*[@id=\"j-sku-discount-price\"]")).Text;
            fetched = true;
        }
        catch
        {
            try
            {
                price = driver.FindElement(By.XPath("//*[@id=\"j-sku-price\"]")).Text;
                fetched = true;
            }
            catch
            {
                fetched = false;
            }
        }
        break;
    }
}

```

Answer: 
You could create a dictionary of available path strings. I don't know what the type of `site` is. I assume `string`

```
private static Dictionary<string, string[]> pricePaths = new Dictionary<string, string[]> {
   [item.SITE.AMAZON] = new string[] { "//*[@id=\"priceblock_ourprice\"]",
                                       "//*[@id=\"priceblock_dealprice\"]" },
   [item.SITE.ALI] = new string[] { "//*[@id=\"j-sku-discount-price\"]",
                                    "//*[@id=\"j-sku-price\"]" },
};

```

With this, you can write a more generic logic.

```
bool fetched = false;
if (pricePaths.TryGetValue(now.site, out string[] paths)) {
    foreach (string path in paths) {
        try {
            price = driver.FindElement(By.XPath(path)).Text;
            fetched = true;
            break;
        } catch {
        }
    }
}

```

It allows you to easily add new sites. The sites can have an arbitrary number of alternate paths.
It appears that you're really trying to get a decimal value. Let's use this assumption and make a method that returns a `decimal?` to indicate success (i.e. a value) or failure (i.e. `null`).

```
public static class Ex
{
    public static decimal? FindDecimalMaybe(this IWebDriver driver, string path)
    {
        try
        {
            if (decimal.TryParse(driver.FindElement(By.XPath(path)).Text, out decimal result))
            {
                return result;
            }
        }
        catch { } // I hate this, but there doesn't seem to be a choice
        return null;
    }
}

```

The purpose of this method is to hide the unpleasant fact that the Selenium library appears to code by exception.

I've also created it as an extension method so that the call to `driver.FindElement` is replaced by something that looks familiar - `driver.FindDecimalMaybe`.

Now I take the same approach as Oliver with a dictionary:

```
private static Dictionary<string, string[]> __pricePaths = new Dictionary<string, string[]>
{
    { item.SITE.AMAZON, new [] { "//*[@id=\"priceblock_ourprice\"]", "//*[@id=\"priceblock_dealprice\"]" } },
    { item.SITE.ALI, new [] { "//*[@id=\"j-sku-discount-price\"]", "//*[@id=\"j-sku-price\"]" } },
};

```

Now it's trivial to get the values out:

```
decimal? price =
    __pricePaths[now.site]
        .Select(path => driver.FindDecimalMaybe(path))
        .Where(x => x.HasValue)
        .FirstOrDefault();

```

If the `price` variable has a value then success, but if it is `null` then the call did not succeed.