2

The goal

Declare some variable within a switch and use it externally.

The problem

I don't know the syntax.

What I'm thought about

To perform my problem, I was thinking to do something like this, but doesn't work because it is just a philosophy:

public ActionResult Compare(int id, string orderBy)
{
    var productsList = Products.BuildIndividualProductComparisonList(id);
    var product = Products.BuildToCompare(id);


        switch (orderBy)
        {
            case "lowestToBiggest":
                var organizedProductsList = 
                    productsList.OrderBy(x => x.minProductPrice);
                break;
            case "biggestToLowest":
                var organizedProductsList = 
                    productsList.OrderBy(x => x.maxProductPrice);
                break;
            default:
                var organizedProductsList = 
                    productsList.OrderBy(x => x.minProductPrice);
                break;
        }

    ComparisonViewModel comparisonViewModel =
        new ComparisonViewModel
        {
            Product = product,
            ProductList = organizedProductsList
        };

    return View(comparisonViewModel);
}

Spotlight

This is my original C#'s code that works good:

public ActionResult Compare(int id, string orderBy)
{
    var productsList = Products.BuildIndividualProductComparisonList(id);
    var product = Products.BuildToCompare(id);

    ComparisonViewModel comparisonViewModel =
        new ComparisonViewModel
        {
            Product = product,
            ProductList = productsList
        };

    return View(comparisonViewModel);
}

The question

Someone has any idea to resolve my problem?

Guilherme Oderdenge
  • 4,935
  • 6
  • 61
  • 96
  • You need to declare a variable of the appropriate type *outside* the scope of your switch statements, then assign to it in your switch – BrokenGlass Jul 29 '13 at 14:13
  • might i recommend adding `switch (orderBy.ToUpper())` and using all uppercase in your `case` statements, to ensure character casing is not an issue – Jonesopolis Jul 29 '13 at 14:14
  • Just a suggestion, but couldn't you create a variable out of the Switch{} scope? Check what the type of organizedProductsList is? – Recipe Jul 29 '13 at 14:14

5 Answers5

8

Declare some variable within a switch and use it externally.

You can't. Variables defined inside the scope would only be visible within that scope.

You have to declare your variable outside the switch statement and then you will be able to use it outside.

I see that you are using var (Implicitly typed variable) and you can't declare it outside of your switch statement, (since that needs to be assigned), You should see: Declaring an implicitly typed variable inside conditional scope and using it outside and the answer from Eric Lippert

Community
  • 1
  • 1
Habib
  • 219,104
  • 29
  • 407
  • 436
6

Declare variable outside switch block and assign value to it. Also try not to use List suffix for collection names:

IEnumerable<Product> sortedProducts;

switch (orderBy)
{
    case "lowestToBiggest":
        sortedProducts = products.OrderBy(x => x.minProductPrice);
        break;
    case "biggestToLowest":
        sortedProducts = products.OrderBy(x => x.maxProductPrice);
        break;
    default:
        sortedProducts = products.OrderBy(x => x.minProductPrice);
        break;
}

Actually your code can be simplified to:

IEnumerable<Product> sortedProducts =
   products.OrderBy(p => orderBy == "biggestToLowest" ?
                         p.maxProductPrice : 
                         p.minProductPrice);
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • Your ternary will be deprecated when there are more than two cases. Any idea? – Guilherme Oderdenge Jul 29 '13 at 14:20
  • @GuilhermeOderdenge it depends.. you want sorting to occur on database server or on client side? About deprecated ternary.. I program to YAGNI, and currently switch block looks deprecated :) – Sergey Berezovskiy Jul 29 '13 at 14:22
  • `orderBy` comes from a URL parameter — I want to sort to display to client. – Guilherme Oderdenge Jul 29 '13 at 14:23
  • @GuilhermeOderdenge I mean products are `IQueryable` or `IEnumerable`(i.e. `List`)? – Sergey Berezovskiy Jul 29 '13 at 14:28
  • Oh, sorry! `IEnumerable` =) – Guilherme Oderdenge Jul 29 '13 at 14:31
  • @GuilhermeOderdenge sorry, was afk. If you need to provide ordering by many different fields, then you have several options - simple switch as above, [Dynamic LINQ](http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx), or [building expression](http://stackoverflow.com/questions/7856060/linq-queries-with-dynamic-order-by) which sorts by property name. I'd go with simple switch, but extracted to separate method `GetProductsOrderdBy(string orderBy` to make your main method cleaner. – Sergey Berezovskiy Jul 29 '13 at 15:42
1

Just put the declaration of the variable outside of the switch block. You have to specify the type of the variable at declaration, though, instead of using var because the type cannot be inferred.

public ActionResult Compare(int id, string orderBy)
{
    var productsList = Products.BuildIndividualProductComparisonList(id);
    var product = Products.BuildToCompare(id);
    var organizedProductsList = null;


        switch (orderBy)
        {
            case "lowestToBiggest":
                organizedProductsList = 
                    productsList.OrderBy(x => x.minProductPrice);
                break;
            case "biggestToLowest":
                organizedProductsList = 
                    productsList.OrderBy(x => x.maxProductPrice);
                break;
            default:
                organizedProductsList = 
                    productsList.OrderBy(x => x.minProductPrice);
                break;
        }

    ComparisonViewModel comparisonViewModel =
        new ComparisonViewModel
        {
            Product = product,
            ProductList = organizedProductsList
        };

    return View(comparisonViewModel);
}
Dennis
  • 14,210
  • 2
  • 34
  • 54
  • If you strongly type the organizedProductsList, should work - but not using 'var'. – Rake36 Jul 29 '13 at 14:14
  • 2
    @BrokenGlass you're right, i was a little too enthusiastic in posting an answer, as other users are always so freaking fast. – Dennis Jul 29 '13 at 14:14
0

You cannot refer to a variable outside its enclosing scope.

Either:

  1. Move the variable to a wider scope. The downside of this is that we always strive to keep scope as narrow as possible.
  2. Extract the switch statement into a function and have it return the value.

Option 1 is, I think, obvious. To expand on option 2, the code would look like this:

ProductList organizedProductsList(...)
{
    return productsList.OrderBy(...);
}

....

ComparisonViewModel comparisonViewModel =
    new ComparisonViewModel
    {
        Product = product,
        ProductList = organizedProductsList(...)
    };
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

You will need declare the variable organizedProductsList outside your case statement, as it will only have scope with the case statement.

Note: I can't tell what Products.BuildIndividualProductComparisonList(id) returns, I presume its a List of Products.

Thus something like:

IEnumerable<Products> organizedProductsList = null;
switch (orderBy)
    {
        case "lowestToBiggest":
            organizedProductsList = 
                productsList.OrderBy(x => x.minProductPrice);
            break;
        case "biggestToLowest":
            organizedProductsList = 
                productsList.OrderBy(x => x.maxProductPrice);
            break;
        default:
            organizedProductsList = 
                productsList.OrderBy(x => x.minProductPrice);
            break;
    }