(How)
C^# You Are - 2 March 2008
This week's questions come from questions in the forums.
- What is the result of the following code? (Forums) Answer
static void Main ( string[] args )
{
Console.WriteLine(String.Format("{{{0:F}}}", 2.45));
}
The result is : {F}
This formatter is tricky and should be avoided. The {{ is converted to a { in the output. The {0 is treated as a formatting
item. The }} is converted to } which results in an unknown format code and is eaten. The final } is sent as an output.
The MSDN help for Composite Formatting goes into this example in detail.
- The following code causes an error saying the connection is closed. What is wrong? (Forums) Answer
public void LoadData ( )
{
using (SqlConnection conn = new SqlConnection(...))
{
conn.Open();
SqlCommand cmd = new SqlCommand(sqlText, conn);
using(SqlDataReader dr = cmd.ExecuteReader())
{
while(dr.Read())
{
dr.GetValue(0);
dr.Close();
};
};
};
}
The problem is that the reader is closed the first time through the reader loop. You should use a using statement around disposable objects
like connections and readers. When you are using the statement then you do not need to call a Dispose or Close routine. You should not
close the object until you are done with it. In this example you should not close the reader or the connection until you have enumerated through all the results. Technically
you do not need to close it at all.
- What is the result of this code? (Forums) Answer
static void Main ( string[] args )
{
double dbl = 4.1 % 2;
}
The answer is 0.999...
Those who have done this long enough realize that computer math isn't perfect but new people struggle with it. Just because you can write a number like 4.1 doesn't
mean the computer can represent it. Instead the computer must translate it into (ultimately) ones and zeros. IEEE defines the format for real numbers. 4.1 isn't an exactly
representable number in IEEE format. Therefore you are more likely dealing with something like 4.999.... Dividing that by 2 (which is exact) results in 0.9999... Still even
when two numbers are exactly representable in IEEE it doesn't mean the result is.
Because of this you should never assume that a real value that you see or generate is an exact representation. What can make this even harder to figure out is the fact that most
programs (including the debugger) will round numbers. Therefore it is possible for the debugger or console to display a number as 1 even when it is 0.999... You should use rounding
and/or specify precision when you want more exact values. In the few cases where it must be extremely accurate you can use Decimal.
- You want to cause a compilation or runtime error when an attribute is assigned an invalid value. How can you do this?(Forums) Answer
Many people misunderstand the purpose of attributes and how they work. An attribute is nothing more than programmer-provided metadata that is attached to the type/member (the target) the attribute
is applied to. Except for a couple of special attributes (like ObsoleteAttribute) attributes have no impact on compilation. They are simply attached to the target as metadata.
Likewise at runtime attributes have no impact on behavior unless explicitly requested by code. The creation of an instance of a type or the invocation of a method does not involve the analysis of
attributes. You would need to code this in or around the instance creation or the method invocation. There are many examples of this. For example when an object is serialized any attributes associated with
serialization are examined. These attributes do not impact other usages of the target.
Another common misconception about attributes is that they are instance-specific. Specifically people try to use attributes as properties where each instance gets its own set of values. Attributes are
metadata associated with the target. Although their properties may be read/write any property assignments only impact the instance of the attribute that is created from the metadata. Each time the attributes
are queried a new copy of the attribute is generated. Therefore the properties found on an attribute are effectively static and apply to all instances of the target.
In answer to the question you can not cause a compilation error on a custom attribute. You can cause a runtime error but only if you can force the creation of the attribute. Attributes are only
created when they are queried so this would require a lot of work.