我该如何重构这段代码?

发布于 2024-10-09 20:49:17 字数 2033 浏览 3 评论 0原文

我有.net 3.5,我想制定一个通用方法。我该如何重构这段代码?

            case (int)Enums.SandwichesHoagies.Cheeses:
                if (this.Cheeses.Where(x => x.Id == product.ProductId).SingleOrDefault() == null)
                {
                    var newCheese = new Cheese
                    {
                        Id = product.ProductId,
                        Name = product.Name,
                        PriceValue = product.Price.HasValue ? (double)product.Price.Value : 0.00
                    };

                    this.Cheeses.Add(newCheese);
                }
                else
                {
                    foreach (var cheese in this.Cheeses.Where(cheese => cheese.Id == product.ProductId))
                    {
                        this.Cheeses.Remove(cheese);
                        break;
                    }
                }

                foreach (var cheese in Cheeses) cheese.Type = string.Empty;

                if (this.Cheeses.Count > 0) Cheeses.First().Type = "Cheeses:";

                break;

            case (int)Enums.SandwichesHoagies.Meats:
                if (this.Meats.Where(x => x.Id == product.ProductId).SingleOrDefault() == null)
                {
                    var newMeat = new Meat
                    {
                        Id = product.ProductId,
                        Name = product.Name,
                        PriceValue = product.Price.HasValue ? (double)product.Price.Value : 0.00
                    };

                    this.Meats.Add(newMeat);
                }
                else
                {
                    foreach (var meat in this.Meats.Where(meat => meat.Id == product.ProductId))
                    {
                        this.Meats.Remove(meat);
                        break;
                    }
                }

                foreach (var meat in Meats) meat.Type = string.Empty;

                if (this.Meats.Count > 0) Meats.First().Type = "Meats:";

                break;

i have .net 3.5 and i would like to make a generic method. how do i refactor this code?

            case (int)Enums.SandwichesHoagies.Cheeses:
                if (this.Cheeses.Where(x => x.Id == product.ProductId).SingleOrDefault() == null)
                {
                    var newCheese = new Cheese
                    {
                        Id = product.ProductId,
                        Name = product.Name,
                        PriceValue = product.Price.HasValue ? (double)product.Price.Value : 0.00
                    };

                    this.Cheeses.Add(newCheese);
                }
                else
                {
                    foreach (var cheese in this.Cheeses.Where(cheese => cheese.Id == product.ProductId))
                    {
                        this.Cheeses.Remove(cheese);
                        break;
                    }
                }

                foreach (var cheese in Cheeses) cheese.Type = string.Empty;

                if (this.Cheeses.Count > 0) Cheeses.First().Type = "Cheeses:";

                break;

            case (int)Enums.SandwichesHoagies.Meats:
                if (this.Meats.Where(x => x.Id == product.ProductId).SingleOrDefault() == null)
                {
                    var newMeat = new Meat
                    {
                        Id = product.ProductId,
                        Name = product.Name,
                        PriceValue = product.Price.HasValue ? (double)product.Price.Value : 0.00
                    };

                    this.Meats.Add(newMeat);
                }
                else
                {
                    foreach (var meat in this.Meats.Where(meat => meat.Id == product.ProductId))
                    {
                        this.Meats.Remove(meat);
                        break;
                    }
                }

                foreach (var meat in Meats) meat.Type = string.Empty;

                if (this.Meats.Count > 0) Meats.First().Type = "Meats:";

                break;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

﹏半生如梦愿梦如真 2024-10-16 20:49:17

假设有两件事:

  1. MeatCheese 继承自 Ingredient 或实现 IIngredient
  2. MeatsCheeses 集合是 IList

这里我们开始:

private void OuterMethod()
{
   switch(something)
   {
       case (int)Enums.SandwichesHoagies.Cheeses:
           HandleCase(product, this.Cheeses);
           break;
       case (int)Enums.SandwichesHoagies.Meats:
           HandleCase(product, this.Meats);
           break;
   }
}

private void HandleCase<T>(Product product, List<T> list) where T : Ingredient, new()
{
    if(list.Any(i => i.Id == product.ProductId))
    {
        list.Add(new T {
            Id = product.ProductId,
            Name = product.Name,
            PriceValue = product.PriceValue ?? 0.0;
        });
    }
    else
    {
        list.RemoveAll(i => i.Id == product.ProductId);
    }

    //NOTE: this part seems like a bad idea. looks like code smell.
    foreach (var i in list)
    {
        i.Type = string.Empty;
    }
    if (list.Count > 0)
    {
        list.First().Type = "Cheeses:";
    }
}

Assuming two things:

  1. Meat and Cheese inherit from Ingredient or implement IIngredient
  2. The Meats and Cheeses collections are IList<T>

Here we go:

private void OuterMethod()
{
   switch(something)
   {
       case (int)Enums.SandwichesHoagies.Cheeses:
           HandleCase(product, this.Cheeses);
           break;
       case (int)Enums.SandwichesHoagies.Meats:
           HandleCase(product, this.Meats);
           break;
   }
}

private void HandleCase<T>(Product product, List<T> list) where T : Ingredient, new()
{
    if(list.Any(i => i.Id == product.ProductId))
    {
        list.Add(new T {
            Id = product.ProductId,
            Name = product.Name,
            PriceValue = product.PriceValue ?? 0.0;
        });
    }
    else
    {
        list.RemoveAll(i => i.Id == product.ProductId);
    }

    //NOTE: this part seems like a bad idea. looks like code smell.
    foreach (var i in list)
    {
        i.Type = string.Empty;
    }
    if (list.Count > 0)
    {
        list.First().Type = "Cheeses:";
    }
}
﹎☆浅夏丿初晴 2024-10-16 20:49:17

乍一看,您有一些可以访问的常用属性:Id、Name、PriceValue 和 Type。对我来说,这看起来像是一个基类或接口。这样,您可以首先将代码重构为方法

void YourMethod<T>(List<T> list, Product product) where T : IProduct, new() 
// IProduct being your interface or base class

,在这种情况下,当您引用 this.Meatsthis.Cheeses 时,您应该引用 list,当您引用 MeatCheese 实例时,只需引用 T 即可。

看看这能让你走多远并进一步重构。

At initial glance, you have some common properties you access, Id, Name, PriceValue, and Type. That looks like a base class or interface to me. With that, you could start by refactoring your code into a method

void YourMethod<T>(List<T> list, Product product) where T : IProduct, new() 
// IProduct being your interface or base class

In which case, where you refer to this.Meats or this.Cheeses, you would instead refer to list, and where you refer to instances of Meat or Cheese, you simply refer to T.

See how far that gets you and refactor further.

给不了的爱 2024-10-16 20:49:17

如果不知道所使用的类型(和基本类型/接口),就很难知道您的确切要求。我假设你正在使用某种 ORM,它无论如何都会吐出部分类。

使其易于使用的第一个要求是 Meat 和 Cheese 共享一个公共接口(或抽象类)。这应该是这样的基本内容。

interface IProduct {
    int Id { get; set; }
    String Name { get; set; }
    Double PriceValue { get; set; }
}

使用分部类的假设使得扩展您的类以使用此接口变得容易。

partial class Cheese : IProduct { }

我发现有趣的是,您有一种不同类型的产品,它具有不同的字段名称,但功能几乎相同。您是否应该保留与上述接口相同的名称,并使其也从该接口派生?不管怎样,假设你拥有的是这样的东西。

class Product {
    int ProductId { get; set; }
    String Name { get; set; }
    Price? Price { get; set; }
}

您要做的第一件事是使用工厂模式来创建特定产品。

public class ProductFactory {
    public T Create<T>(Product product) 
      where T : IProduct, new() {
        return new T {
            Id = product.ProductId,
            Name = product.Name,
            PriceValue = product.Price.HasValue 
                ? (double)product.Price.Value 
                : 0.00    
        };
    }
}

new() 约束需要 Cheese 和 Meat 类中的无参数构造函数。我认为这没有问题。您只需要调用 .Create(product);

接下来的部分,我需要假设您的 Cheeses 和 Meats 对象(或属性)也共享一个公共类(ICollection),或者您可以根据特定需求定义自己的。

public class ProductCollection : ICollection<IProduct> { ... }

检查产品是否存在的通用方法

Boolean ContainsProduct<T>(ProductCollection<T> collection, Product product) 
  where T : IProduct {
    return collection.Where(x => x.Id == product.Id).SingleOrDefault != null;
}

我对您在 foreach 循环内调用 .Remove 的想法表示怀疑。修改集合可能会导致用于循环遍历集合的枚举器出现问题。如果这是一个问题,我会找到更好的方法。

Hard to know your exact requirements without knowing the types (and base types/interfaces) used. I'm going to assume you're using some kind of ORM which spits out partial classes anyway.

First requirement to make this easy to work with, is that Meat and Cheese share a common interface (or abstract class). This should be something basic like this.

interface IProduct {
    int Id { get; set; }
    String Name { get; set; }
    Double PriceValue { get; set; }
}

The assumption that partial classes are used makes it easy to extend your class to use this interface.

partial class Cheese : IProduct { }

I find it interesting that you have a different kind of Product which has different field names, but almost the same features. Should you perhaps keep the names the same as the above interface and make this also derived from the interface? Anyway, assuming what you have is something like this.

class Product {
    int ProductId { get; set; }
    String Name { get; set; }
    Price? Price { get; set; }
}

The first thing you wanna do is use the Factory Pattern to create a specific product.

public class ProductFactory {
    public T Create<T>(Product product) 
      where T : IProduct, new() {
        return new T {
            Id = product.ProductId,
            Name = product.Name,
            PriceValue = product.Price.HasValue 
                ? (double)product.Price.Value 
                : 0.00    
        };
    }
}

The new() constraint requires a parameterless constructor in your Cheese and Meat classes. I assume this is no problem. You just need to call .Create<Cheese>(product);

The next parts, I would need to assume that your Cheeses and Meats objects (or properties), also share a common class (ICollection<IProduct>), or you could define your own for particular needs.

public class ProductCollection : ICollection<IProduct> { ... }

A generic method to check if a product exists

Boolean ContainsProduct<T>(ProductCollection<T> collection, Product product) 
  where T : IProduct {
    return collection.Where(x => x.Id == product.Id).SingleOrDefault != null;
}

I'm skeptical of your idea of calling .Remove inside a foreach loop. Modifying a collection can cause problems for the enumerator being used to loop through it. I would find a better approach to that if it's a concern.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文