String
1. Enum with string type?
The UK mentions such a problem in the various enumerations:
The member types of the enumeration are numeric, what are the ways to do a character-type enumeration?
Enum colors:string{
Red= ' #ff0000 ',
}
Before we start the discussion, I think it is necessary to find out another problem, the "#ff0000" in the code is not a character but a string, should be changed to "#ff0000", so the UK's problem is also smoothly changed to "want to do a string enumeration has any way."
Quite frankly,. NET does not support such a string enumeration. Also, not all numeric types can be the underlying type of an enumeration, the underlying type of an enumeration can only be an integer type, which means that one day you want to define an enumeration with the underlying type double, and you will receive a warning letter from the compiler.
The UK code does raise the requirement that colors is like an enumeration, but the value of its members is a string, so it is easy for us to have the question of whether we can simulate such an enumeration.
2. Is there a way to simulate it?
Before writing any code, let's first think about how we would use it if there was a Color class. Here are two uses I've come up with:
1//Code #01
2
3Color C1 = color.red;
4string S1 = (string) c1;
5debug.assert (S1 = = "#FF0000");
6
7Color C2 = (Color) "#00FF00";
8Debug. Assert (C2 = = Color.green);
First, enumerations are initialized by their members rather than constructors, as in the third line of the code above. So, we should make the constructor private, simulate some of the enumeration members and expose it:
Code #02
public class Color
{
Private Color (String value)
{
M_value = Value;
}
private string m_value;
public static readonly Color Red = new Color ("#FF0000");
public static readonly Color Green = new Color ("#00FF00");
public static readonly Color Blue = new Color ("#0000FF");
}
In this way, the third line of the Code #01 can work. It is worth reminding that the values of members such as Red, Green, and Blue are constant, and I set them to ReadOnly in order not to allow the client code to modify their values (note: they cannot be set to const, do you know why?) )。 In addition, they should belong to a Color class instead of an instance, so they are set to static.
Next, line Fourth of the Code #01 illustrates that an instance of Color can be cast to a string, which can be done by overloading the conversion operator:
Code #03
public static explicit operator string (Color value)
{
return value.m_value;
}
The fourth line to the code #01 corresponds to line seventh of the Code #01, which shows that the string can be coerced into a Color instance, which is also done through an overloaded conversion operator:
Code #04
public static explicit operator Color (string value)
{
switch (value)
{
case "#FF0000":
return Red;
Case "#00FF00":
return Green;
Case "#0000FF":
return Blue;
Default:
throw new InvalidCastException ();
}
}
Obviously, not all strings can be converted to a color instance, so when the client code tries to convert a string containing an unexpected value into a color instance, it should throw a InvalidCastException.
Admittedly, some people are disgusted with the Code #04 because it has a switch! When we use enumerations, we don't just use it to convert some values or get their literal value, we'd rather use it to identify different situations or categories, and to judge which cases or categories are based on the values of the enumerated instances. In other words, when we decide to use enumerations, we are destined to bond with conditional statements.
Finally, here's the complete code for Color:
Code #05
Color#region Color
public class Color
{
Private Color (String value)
{
M_value = Value;
}
public static explicit operator Color (string value)
{
Switch (value)
{
Case "#FF0000":
return Red;
Case "#00FF00":
return Green;
Case "#0000FF":
return Blue;
Default
throw new InvalidCastException ();
}
}
public static explicit operator string (Color value)
{
return value.m_value;
}
public override string ToString ()
{
return m_value;
}
public static readonly Color Red = new Color ("#FF0000");
public static readonly Color Green = new Color ("#00FF00");
public static readonly Color Blue = new Color ("#0000FF");
private string m_value;
}
#endregion
One might ask the question: We often judge the enumeration, but why is there no overloaded Object.Equals method in the Code #05 and no = = and!= operators? With a careful look at the color code, you'll find that there are only two ways to get color: through static read-only fields and through cast operators, but no matter how you get the instance of color, these instances are ultimately static, read-only fields from within the color. In other words, the two Color instances obtained by these two approaches are actually the same instance.
3. What is the problem with the simulation program?
I believe that color can meet the needs of the UK to a certain extent, but I don't think color is necessarily used in practical applications. Looking back at Code #05, Color is both an enumeration and a data carrier. Say it is an enumeration because we deliberately simulate it as an enumeration, and say it is a data carrier because we do not use it merely as an enumeration, and what we need more is the value represented by the member behind it. This means that Color bears more than one responsibility and violates the principle of single liability (SRP).
I suspect that the UK's desire for Color is more or less influenced by the part of the value of the enumeration member in the various enumerations, especially "Why do I need to manually specify the value of an enumeration member?" "The answer to this question. If so, I must apologize for the misleading of this article. The reality is often not as simple as the Code #13 that the same type of customer (such as platinum members) can enjoy the discount at any time will change, and the same product at different times (such as promotional period) discounts may also be different, The discount that customers can eventually enjoy is probably a combined discount for complex operations. Any hard coding of the change factor will cause the system to be ossified! I suggest that this part of the text should be read in order to study the characteristics of the enumeration.
On the other hand, Color as a data carrier, it is really weak. Currently it only contains R, G, B three channels of data, if I want to join the alpha channel data? How much impact does this have on its code? What if I want it to be able to extract data for a, R, G, B four channels, respectively? What if I want to implement data conversion between RGB and CMYK? I believe these problems have been enough to give you a headache for a week, but when you know that the human eye can identify about 16 million colors, and these colors can be described by the RGB value and as the monitor output basis, your mouse will immediately point to the top right corner of the browser intersection?
Obviously, the color given here cannot withstand the test of time, so I wonder how the. NET Framework expresses color? And how does it meet these depressing needs?
4. How does the. NET Framework Express Color?
In the. NET Framework, there are 3 things related to the requirements mentioned here: The Color structure, the KnownColor enumeration, and the ColorTranslator class, all in the System.Drawing namespace.
First, let's say the KnownColor enumeration, its members can be divided into two categories: one is the color of the name, and their corresponding RGB value is unchanged, such as Indigo is Indigo; the other is the color of the appearance items, and their corresponding RGB values will change with the user's settings, such as InfoText is the color of the ToolTip text.
followed by the color structure, which has a lot of static properties, which are the color instances that correspond to the first class of members in the KnownColor enumeration. It also provides the FromKnownColor and ToKnownColor methods to implement transformations between its instance and the KnownColor enumeration. Of course, because it is a data carrier, it contains a, R, G, B four channels of data, and its instance of the sentence is equivalent to the data to be sentenced, so it also overloads the = = and!= operators.
Having said so much, it doesn't seem to mention how to get HTML color values from a color instance, okay, now it's time to get the ColorTranslator class on. This class provides conversions between strings that are used by the ToHtml and fromhtml methods to implement color-instance and HTML-colored values.
The responsibilities of these three things are clear, when you need to determine whether a certain color is used, there is no need to compare their A, R, G, B Four channel data, what you really need is a fast and accurate identification contrast, KnownColor enumeration just can meet this requirement When you need to manipulate a color of data, you do not want to manipulate a string, the color structure allows you to easily extract the required data; When you convert between color data and HTML color values, you don't really need an enumeration to identify. However, you might also be able to combine them with three of them, and here's an example to end this article:
Code #06
String desktopcolorvalue = colortranslator.tohtml (Color.fromknowncolor (knowncolor.desktop));