C# 减少重复代码
我有一些关于颜色结构的代码,就像这样C# 减少重复代码,c#,readability,C#,Readability,我有一些关于颜色结构的代码,就像这样 public void ChangeColor() { thisColor.R = thisColor.R + 5; } 现在我需要创建一个方法,根据传递的内容更改不同的变量。下面是代码现在的样子 public void ChangeColor(int RGBValue) { switch(RGBValue) { case 1: thisColor.R = thisColor.R + 5;
public void ChangeColor()
{
thisColor.R = thisColor.R + 5;
}
现在我需要创建一个方法,根据传递的内容更改不同的变量。下面是代码现在的样子
public void ChangeColor(int RGBValue)
{
switch(RGBValue)
{
case 1:
thisColor.R = thisColor.R + 5;
break;
case 2:
thiscolor.B = thisColor.B + 5;
break;
}
}
现在,这是我通常不会质疑的事情,我只是在它周围抛出一个#region语句,并称之为一天,但这只是我的一个例子,实际函数相当长
我希望它看起来像这样:
public void ChangeColor(int RGBValue)
{
thiscolor.RGBValue = thiscolor.RGBValue;
}
var props = new Dictionary<string, Tuple<Func<Color, int>, Action<Color, int>>>
{ "R", Tuple.Create(c => c.R, (c, r) => c.R = r),
"G", Tuple.Create(c => c.G, (c, g) => c.G = g),
"B", Tuple.Create(c => c.B, (c, b) => c.B = b) };
public void ChangeColor(string propName) {
var getSet = props[propName];
getSet.Item2(thisColor, getSet.Item1(thisColor) + 5);
}
int ThisColor { get; set; }
public void ChangeColor(Func<int> getter, Action<int> setter)
{
setter(getter() + 5);
}
public void SomeMethod()
{
ChangeColor(() => ThisColor, (color) => ThisColor = color);
}
public void ChangeColor(int RGBValue)
{
thisColor.{something-from-RGBValue} += 5;
}
因此,本质上,该值将引用正在使用的变量。这个有名字吗?这就是反思的目的吗?或者类似的事情。。。有没有办法做到这一点?我不能100%确定这是否是你想要的。但在给出的例子中,听起来这可能就是你想要的 您可以使用
ref
关键字:
public void ChangeColor(ref int color)
{
color += 5;
}
void SomeMethod()
{
ChangeColor(ref thisColor.R); //Change the red value
ChangeColor(ref thisColor.B); //Change the blue value
}
我倾向于使用字典,而不是我认为可能最终成为一个大型switch语句的东西,因此如果您创建了
Dictionary<int,Func<int,int>> map = new Dictionary<int, Func<int, int>>();
它将针对插入的Rgb值执行特定于代理的操作,要分配代理,只需向地图添加一个新条目即可
map.Add(5,x => x+5);
如果我理解正确,您希望编写一个方法,该方法采用一些符号(或属性名称),并使用此符号定义的值修改结构的属性。这在C#中不容易实现(当然可以使用反射,但是…) 您可以使用包含用于读取和写入属性值的委托的
字典执行类似的操作。但是,这仍然有点长,因为您需要初始化字典。无论如何,代码可能如下所示:
public void ChangeColor(int RGBValue)
{
thiscolor.RGBValue = thiscolor.RGBValue;
}
var props = new Dictionary<string, Tuple<Func<Color, int>, Action<Color, int>>>
{ "R", Tuple.Create(c => c.R, (c, r) => c.R = r),
"G", Tuple.Create(c => c.G, (c, g) => c.G = g),
"B", Tuple.Create(c => c.B, (c, b) => c.B = b) };
public void ChangeColor(string propName) {
var getSet = props[propName];
getSet.Item2(thisColor, getSet.Item1(thisColor) + 5);
}
int ThisColor { get; set; }
public void ChangeColor(Func<int> getter, Action<int> setter)
{
setter(getter() + 5);
}
public void SomeMethod()
{
ChangeColor(() => ThisColor, (color) => ThisColor = color);
}
public void ChangeColor(int RGBValue)
{
thisColor.{something-from-RGBValue} += 5;
}
如果您将自己的类型与Get
属性和Set
属性一起使用,而不是将Tuple
与名为Item1
和Item2
的属性一起使用,则代码的可读性会更高。此解决方案在某些情况下可能很有用,但在初始化字典时仍需要显式列出所有属性。这可能是您需要的,但您可能需要添加一些错误处理。
它将适用于任何类型的公共财产;并设置;方法。
如果你想,有办法减少使用“魔术弦”
公共静态void ChangeProperty(此对象对象对象,字符串属性名称,Func Func)
{
var pi=obj.GetType().GetProperty(propertyName);
pi.SetValue(obj,func((T)pi.GetValue(obj,null)),null);
}
公共空间更改()
{
thisColor.ChangeProperty(“R”,(x)=>x+5);
}
由于您给出了一个非常简单的示例,因此很难判断到底发生了什么
但是,我真正读到的是,您希望有一个方法,该方法将根据该方法的一个参数对局部状态执行一系列可能的修改
现在,除了对什么进行操作之外,操作是否相同
最终,您必须有一些能够理解将输入映射到所需操作的代码。可以概括的程度取决于动作的相似程度(如果总是“向属性添加5”,则您有更多的概括选项…)
您有以下几种选择:
编写一个封装颜色结构的类
按照Kev Hunter的建议,使用操作
s的查找表
写一个switch语句
传入一个参数,该参数包含一个可以对内部数据执行的虚拟方法(或直接传入一个操作)——避免查找
而且。。。就是这样,真的。其中哪一个最有意义可能更多地取决于您的实际用例(我们没有太多的信息),而不是其他任何东西。这有点尴尬,但您可以像这样“按引用”传递属性:
public void ChangeColor(int RGBValue)
{
thiscolor.RGBValue = thiscolor.RGBValue;
}
var props = new Dictionary<string, Tuple<Func<Color, int>, Action<Color, int>>>
{ "R", Tuple.Create(c => c.R, (c, r) => c.R = r),
"G", Tuple.Create(c => c.G, (c, g) => c.G = g),
"B", Tuple.Create(c => c.B, (c, b) => c.B = b) };
public void ChangeColor(string propName) {
var getSet = props[propName];
getSet.Item2(thisColor, getSet.Item1(thisColor) + 5);
}
int ThisColor { get; set; }
public void ChangeColor(Func<int> getter, Action<int> setter)
{
setter(getter() + 5);
}
public void SomeMethod()
{
ChangeColor(() => ThisColor, (color) => ThisColor = color);
}
public void ChangeColor(int RGBValue)
{
thisColor.{something-from-RGBValue} += 5;
}
intthiscolor{get;set;}
公共void ChangeColor(Func getter、Action setter)
{
setter(getter()+5);
}
公共方法()
{
ChangeColor(()=>ThisColor,(color)=>ThisColor=color);
}
这比反射便宜,而且它是编译时检查的(使用反射,您必须将字符串传递给GetProperty调用,并且在以后的重构中字符串名称可能会与属性名称不同。)这绝对不是反射的目的。事实上,这里似乎有很多问题。让我们在此回顾一下-您希望更改以下方法:
public void ChangeColor(int RGBValue)
{
switch(...)
{
case ...
case ...
case ...
}
}
变成这样:
public void ChangeColor(int RGBValue)
{
thiscolor.RGBValue = thiscolor.RGBValue;
}
var props = new Dictionary<string, Tuple<Func<Color, int>, Action<Color, int>>>
{ "R", Tuple.Create(c => c.R, (c, r) => c.R = r),
"G", Tuple.Create(c => c.G, (c, g) => c.G = g),
"B", Tuple.Create(c => c.B, (c, b) => c.B = b) };
public void ChangeColor(string propName) {
var getSet = props[propName];
getSet.Item2(thisColor, getSet.Item1(thisColor) + 5);
}
int ThisColor { get; set; }
public void ChangeColor(Func<int> getter, Action<int> setter)
{
setter(getter() + 5);
}
public void SomeMethod()
{
ChangeColor(() => ThisColor, (color) => ThisColor = color);
}
public void ChangeColor(int RGBValue)
{
thisColor.{something-from-RGBValue} += 5;
}
这方面的问题是:
- 该方法的名称,
ChangeColor
,不能准确描述该方法的实际功能。也许这是匿名化的产物,但对于这种方法来说,这是一个可怕的名字
- 参数“
RGBValue
”不能准确描述参数是什么或做什么。名称RGBValue
和类型int
使其听起来像实际的RGB颜色值,即0x33ccff表示浅蓝色。相反,它选择设置R、G或B中的哪一个
- 参数只有3个有效值,但可能值的范围完全不受限制。这是虫子的配方。更糟糕的是,单个值在方法中被用作幻数
- 但也许最重要的是,您要求的“干净/快速方法”正是该方法声称提供的抽象您正在编写一种增强色调的方法,为了使方法简短,您要求。。。增强色调的方法。这没有道理
我只能假设您想要这样做,因为您可能需要对颜色执行许多不同的操作,例如:
public void Brighten(...) { ... }
public void Darken(...) { ... }
public void Desaturate(...) { ... }
public void Maximize(...) { ... }
等等等等。并且您试图避免为所有人编写switch
语句
可以,但不要完全取消开关
;到目前为止,它是