减少重复代码
我有一些适用于这样的颜色结构的代码
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;
}
所以本质上该值将引用正在使用的变量。这个有名字吗?这就是反射的目的吗?或者类似的东西......有办法做到这一点吗?
I have some code that works on the color structure like this
public void ChangeColor()
{
thisColor.R = thisColor.R + 5;
}
Now I need to make a method that changes a different variable depending on what it is passed. Here is what the code looks like now.
public void ChangeColor(int RGBValue)
{
switch(RGBValue)
{
case 1:
thisColor.R = thisColor.R + 5;
break;
case 2:
thiscolor.B = thisColor.B + 5;
break;
}
}
Now, this is something I would normally never question, I'd just throw a #region statement around it and call it a day, but this is just an example of what I have, the actual function is quite long.
I want it to look like this:
public void ChangeColor(int RGBValue)
{
thiscolor.RGBValue = thiscolor.RGBValue;
}
So essentially the value would refer to the variable being used. Is there a name for this? Is this what Reflection is for? Or something like that... Is there a way to do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我不确定这是否是您想要的。但通过给定的示例,听起来这可能就是您所追求的。
您也许可以使用
ref
关键字:I'm not 100% sure if this is what you want. But with the given example, it sounds like this might be what you're after.
you might be able to use the
ref
keyword:这绝对不是反射的目的。事实上,这里似乎存在很多问题。让我们回顾一下这里 - 您想要将以下方法更改
为这样的内容:
这样做的问题是:
方法的名称
ChangeColor
不准确 描述该方法实际执行的操作。也许这是匿名化的产物,但无论如何,对于该方法来说,这是一个糟糕的名称。参数
RGBValue
没有准确描述参数是什么或做什么。名称RGBValue
和类型int
使其听起来像实际的 RGB 颜色值,即 0x33ccff 表示浅蓝色。相反,它选择设置 R、G 或 B 中的哪一个。该参数只有 3 个有效值,但可能值的范围完全不受限制。这是错误的秘诀。更糟糕的是,单个值在方法内用作幻数。
但也许最重要的是,您所要求的“干净/快速方法”正是该方法旨在提供的抽象!您正在编写一种增强色调的方法,为了使方法简短,您需要...一种增强色调的方法。这没有意义!
我只能假设您想要这样做,因为您可能想要对颜色做许多不同的事情,例如:
等等。并且您试图避免为所有内容编写
switch
语句。很好,但不要完全消除
switch
;这是迄今为止编写此代码的最有效的和可读方式!更重要的是把它提炼成一个switch
而不是很多,并解决上面提到的其他问题。首先,让我们从一个合理的参数类型开始,而不是一个int
- 创建一个枚举:现在,从这样的想法开始:我们可能想要对复合的其中一种原色执行许多操作color,所以编写通用方法:
这个方法很短,易于阅读,并且可能永远不需要更改。这是一个好的、干净的方法。现在我们可以很容易地编写单独的操作方法:
这样做的(显着)优点是:
枚举类型可以防止调用者搞砸并传递无效的参数值。
一般的
Adjust
方法易于阅读,因此易于调试和维护。它也将比任何基于反射或基于字典的方法表现得更好 - 性能并不是这里关注的问题,但我主要是想指出它肯定不会更糟 em>.您不必编写重复的
switch
语句。每个单独的修饰符方法都是一行。最终,某个地方,你实际上必须编写一些代码,我更希望代码是一个极其简单的
switch
语句而不是一堆混乱的反思、代表、字典等。关键是尽可能地概括这项工作;一旦您完成了该操作并创建了该抽象,然后您就可以开始编写一行方法来完成“真正的”工作。This is definitely not what reflection is for. In fact, there seem to be a number of issues here. Let's review here - you want to change the following method:
Into something like this:
The problems with this are:
The name of the method,
ChangeColor
, does not precisely describe what the method actually does. Perhaps this is an artifact of anonymization, but nevertheless it's a terrible name for the method.The parameter,
RGBValue
, does not accurately describe what the argument is or does. The nameRGBValue
and the typeint
makes it sound like an actual RGB color value, i.e. 0x33ccff for a light blue. Instead it chooses which of R, G, or B will be set.There are only 3 valid values for the parameter, and yet the range of possible values is completely unrestricted. This is a recipe for bugs. Worse, individual values are used as magic numbers inside the method.
But perhaps most important of all, the "clean/quick method" you are asking for is precisely the abstraction that this method purports to provide! You're writing a method that intensifies the hue, and in order to keep the method short, you're asking for... a method to intensify the hue. It doesn't make sense!
I can only assume that you want to do this because you have many different things you might want to do to a Color, for example:
And so on and so forth. And you're trying to avoid writing
switch
statements for all.Fine, but don't eliminate the
switch
entirely; it is by far the most efficient and readable way to write this code! What's more important is to distill it down to oneswitch
instead of many, and fix the other problems mentioned above. First, let's start with a reasonable parameter type instead of anint
- create an enumeration:Now, start from the idea that there may be many actions we want to perform on one of the primary colors of a composite color, so write the generic method:
This method is short, easy to read, and will likely never have to change. It is a good, clean method. Now we can write the individual action methods quite easily:
The (significant) advantages to this are:
The enumeration type prevents callers from screwing up and passing in an invalid parameter value.
The general
Adjust
method is easy to read and therefore easy to debug and easy to maintain. It's also going to perform better than any reflection-based or dictionary-based approach - not that performance is likely a concern here, but I'm mainly saying this to note that it certainly isn't going to be worse.You don't have to write repeated
switch
statements. Each individual modifier method is exactly one line.Eventually, somewhere, you're actually going to have to write some code, and I would much rather that code be an extremely simple
switch
statement than a mess of reflection, delegates, dictionaries, etc. The key is to generalize this work as much as possible; once you've done that and created that abstraction, then you can start writing one-liner methods to do the "real" work.这有点尴尬,但是您可以像这样“通过引用”传递属性:
这比反射更便宜,并且它是编译时检查的(使用反射,您必须将字符串传递给 GetProperty 调用和字符串名称在以后的重构中可能会与属性名称有所不同。)
It's a bit awkward, but you can pass a property 'by ref' like this:
This is less expensive than reflection and it's compile-time checked (with reflection, you'd have to pass a string to a GetProperty call and the string name could potentially diverge from the property name in later refactoring.)
我倾向于使用字典,而不是我怀疑最终可能成为一个大的 switch 语句,因此,如果您创建了
字典中的每个项目,则可以输入并返回新值,
这样您的方法就可以调用
哪个将执行特定于您插入的 Rgb 值的委托,要分配委托,您只需向映射添加一个新条目
I would tend to use a dictionary rather than what i suspect could end up being a large switch statement so if you created a
Each item in your dictionary could take then input and return the new value
so you your method you would be able to call
which will execute the delegate specific for the Rgb value you insert, to assign a delegate you simply add a new entry to the map
如果我理解正确,您希望编写一个方法,该方法采用一些符号(或属性名称)并使用此符号定义的结构修改属性。这在 C# 中不容易实现(您当然可以使用反射,但是......)。
您可以使用包含用于读取和写入属性值的委托的
Dictionary
来执行类似的操作。但是,这仍然有点冗长,因为您需要初始化字典。无论如何,代码可能如下所示:这将创建一个字典,其中包含作为键的字符串(属性的名称)以及一个包含每个属性的 getter 委托和 setter 委托的元组。现在,您的
ChangeColor
方法可能如下所示:如果您使用自己的类型以及
Get
属性和Set
属性而不是Tuple
具有名为Item1
和Item2
的属性。该解决方案在某些场景中可能有用,但您仍然需要在初始化字典时显式列出所有属性。If I understand you correctly, you'd like to write a method that takes some symbol (or property name) and modifies the property of the structure using defined by this symbol. This isn't easily possible in C# (you could of course use reflection, but...).
You could do similar thing using
Dictionary
containing delegates for reading and writing the value of the property. However, that will still be a bit lengthy, because you'll need to initialize the dictionary. Anyway, the code might look like this:This creates a dictionary that contains string (name of the property) as the key and a tuple with getter delegate and setter delegate for each of the property. Now your
ChangeColor
method could look like this:The code would be more readable if you used your own type with
Get
property andSet
property instead ofTuple
with properties namedItem1
andItem2
. This solution may be useful in some scenarios, but you still need to explicitly list all the properties when initializing the dictionary.这可能正是您所寻找的,但您可能想添加一些错误处理。
它适用于任何类型的公共财产;并设置;方法。
如果你愿意的话,有一些方法可以减少“魔弦”的使用。
This might be what your looking for, you may want to add some error handling though.
It will work with any kind of property with public get; and set; methods.
And if you want to there is ways to reduce use of "magic-strings".
好吧,由于您给出了一个非常简单的示例,所以很难判断到底发生了什么。
但是,我真正读到的是,您想要一种方法,该方法将根据该方法的参数之一对本地状态执行多种可能的修改之一。
现在,除了要做什么之外,操作是否相同?
最终,您必须拥有一些能够理解将输入映射到所需操作的代码。可以概括的程度取决于操作的相似程度(如果始终“向属性添加 5”,则您有更多的概括选项...)。
您有一些选择:
Action
的查找表。并且......就是这样,真的。其中哪一个最有意义可能更多地取决于您的实际用例(我们实际上没有太多信息)而不是其他任何因素。
Well, it's kind of hard to tell what's really going on since you've given a very simplified example.
But, what I'm really reading is that you want to have a method that will perform one of a number of possible modifications to local state based upon one of the parameters of the method.
Now, is the operation the same, except for what it's being done to?
Ultimately, you have to have some code that understandds that maps an input to a desired operation. How much that can be generalized depends upon how similar the actions are (if it's always 'add 5 to a property' you have more generalization options...).
Some options you have are:
Action
s, as suggested by Kev Hunter.And... that's about it, really. Which one of these makes the most sense probably depends more on your actual use case (which we don't really have a lot of info on) than anything else.