I've been trying to use decimal values as params for a field attribute but I get a compiler error.
I found this blog post link saying it wasn't possible in .NET to use then, does anybody know why they choose this or how can I use decimal params?
This is a CLR restriction. Only primitive constants or arrays of primitives can be used as attribute parameters. The reason why is that an attribute must be encoded entirely in metadata. This is different than a method body which is coded in IL. Using MetaData only severely restricts the scope of values that can be used. In the current version of the CLR, metadata values are limited to primitives, null, types and arrays of primitives (may have missed a minor one).
Decimals while a basic type are not a primitive type and hence cannot be represented in metadata which prevents it from being an attribute parameter.
I have the same problem. I consider to use strings. This is not type-safe, but it's readable and I think we will be able to write valid numbers in strings :-).
class BlahAttribute : Attribute
{
private decimal value;
BlahAttribute(string number)
{
value = decimal.Parse(number, CultureInfo.InvariantCulture);
}
}
[Blah("10.23")]
class Foo {}
It's not a beauty, but after considering all the options, it's good enough.
When I have run into this situation, I ended up exposing the properties on the attribute as a Double, but inside the attribute treated them like Decimal. Far from perfect, but for the simple cases, it just might be what you need.
For realtime tricks with attributes i am using TypeConverter class.
You can use the following constructor. When you have a decimal literal in C# code, the C# compiler emits a call to this constructor.
Decimal(Int32, Int32, Int32, Boolean, Byte)
Edit: I know this is not convenient.
Related
Given a string : "5.2m*5.7m"
and return type being Decimal;
and calling
`System.Linq.Dynamic.DynamicExpression.Parse(returnType, expression);`
will give a syntax error regarding the character on position which is 'm';
After a bit of testing the same applies to 'd';
To give a bit of context,the reason to use m is to avoid another error which is multiplication of double*decimal as it will interpret a floating point value as double by default.
My question is: Why does this happen? and what would be the best scenario of solving the double*decimal problem? cast by means of (decimal)5.7 the value I know to be decimal or use Convert.ToDecimal(5.7)?How much really does parse() know?(I didn't find documentation on msdn or the like)
My question is: Why does this happen?
This happens because DynamicExpression uses a custom-built expression parser. It is made to resemble C# but it is not C#. Not everything that is valid in C# will work, and some things that are valid in C# work differently.
and what would be the best scenario of solving the double*decimal problem? cast by means of (decimal)5.7 the value I know to be decimal or use Convert.ToDecimal(5.7)?
Cast, but not using this syntax. The syntax to use is type(expr), not (type)expr, see below.
How much really does parse() know?(I didn't find documentation on msdn or the like)
A copy of the original documentation appears to be available at http://ak-dynamic-linq.azurewebsites.net/GettingStarted. I have not verified that the whole document is unmodified, but I have compared the below to the original documentation.
To quote:
The expression language permits explicit conversions using the syntax type(expr) or type"string", where type is a type name optionally followed by ? and expr is an expression or string is a string literal. This syntax may be used to perform the following conversions:
Between two types provided Type.IsAssignableFrom is true in one or both directions.
Between two types provided one or both are interface types.
Between the nullable and non-nullable forms of any value type.
Between string and any type that have static TryParse method.
Between any two types belonging to the set consisting of SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Decimal, Single, Double, Char, any enum type, as well as the nullable forms of those types.
Why and when should we use int, int16, int32, int64, double, string instead of Int, Int16, Int32, Int64, Double, String respectively? I have ready many articles about this but still not getting a proper solution.
This is purely a matter of preference/tradition.
C# language specification states:
Each of the predefined types is shorthand for a system-provided type. For example, the keyword int refers to the struct System.Int32. As a matter of style, use of the keyword is favoured over use of the complete system type name.
It doesn't matter at all in implementation. I personally prefer using the aliases, and from what I've seen of other code that's the more common choice. There are some who suggest using the BCL names (Int32 etc) everywhere though - including Jeffrey Richter, author of CLR via C# (where he gives that advice).
However, when you're naming methods and types, you should use the BCL name rather than the C#-specific name. That way your code is equally idiomatic to people using your code from other languages. This is the convention adopted within the BCL itself. For example, we have Convert.ToInt32 and Convert.ToSingle instead of Convert.ToInt and Convert.ToFloat.
While it doesn't matter in theory if those are internal or private members, I'd suggest getting in the habit of giving your members the names you'd want to expose publicly - it means you can be consistent there regardless of access, and you're less likely to accidentally let one slip through.
It truly does not matter, just be consistent. I personally use the original, lowercase names.
.NET knows many ways to convert data types:
Convert-class;
Functions inside a type like (Try)Parse and ToString, etc.;
Implementation of interface IConvertable;
The TypeConverter;
The implicit and explicit conversion operator;
Am I missing another one?
So if am converting one datatype to another, I need to know both types and I need to know which conversion method to use. And this becomes pretty nasty if one of those two types (or both) is a generic type.
So my question is: I there is uniform (generic) way in .NET to convert one data type to another, which might use all the other limited methods?
A good, generic way to convert between types is with Convert.ChangeType. Here's an example of how you could use it to write a generic converting method:
public static TResult Convert<TResult>(IConvertible source)
{
return (TResult)System.Convert.ChangeType(source, typeof(TResult));
}
It, like other Convert methods, internally calls the IConvertible interface.
This will not make use of your other conversion options:
The most common I'd think would be ToString; for that, you could add a check to see if TResult is string and if so, (after appropriate null checks) simply call ToString on your input.
Using reflection you could check for:
the TypeConverterAttribute (TypeDescriptor.GetConverter seems to be the way to go from there)
(Try)Parse methods, (which you'd invoke), and
implicit/explicit conversion operators (the methods op_Implicit and op_Explicit, which you'd likewise invoke)
These are each fairly self-explanatory if you know a bit about reflection, but I could elaborate if any prove difficult.
You imply those are all the same
They are not
Pick the appropriate
Convert Class
Converts a base data type to another base data type.
Parse is from string
ToString is a to string
IConvertible Interface
Defines methods that convert the value of the implementing reference
or value type to a common language runtime type that has an equivalent
value.
TypeConverter Class
Provides a unified way of converting types of values to other types,
as well as for accessing standard values and subproperties.
Yes you need to know the type you are converting to.
And you should be aware if the type you are converting from.
With generics there is no built in.
At best you provide a method.
But why do you need to convert generics?
You seem to imply that more than one way is a bad thing.
For a single way then I like the answer from Tim S. +1
But that does not mean I would ever use it.
The are even more ways to get data from a SQL database.
Is that a bad thing?
Why can you do things like
int i = 10;
i.ToString();
'c'.Equals('d');
1.ToString();
true.GetType();
in C#? Those things right there are either primitive, literal, unboxed, or any combination of those things; so why do they have methods? They are not objects and so should not have methods. Is this syntax sugar for something else? If so, what? I can understand having functions that do these things, for example:
string ToString(int number)
{
// Do mad code
return newString;
}
but in that case you would call it as a function, not a method:
string ranch = ToString(1);
What's going on here?
edit:
Just realised C# isn't a java clone anymore and the rules are totally different. oops :P
They act like that because the spec says so (and it's pretty nice) :
1.28 Value types
A value type is either a struct type or an enumeration type. C# provides a set of predefined struct types called the simple types.
The simple types are identified through reserved words.
...
1.28.4 Simple types
C# provides a set of predefined struct types called the simple types.
The simple types are identified through reserved words, but these
reserved words are simply aliases for predefined struct types in the
System namespace, as described in the table below.
...
Because a simple type aliases a struct type, every simple type has
members. For example, int has the members declared in System.Int32 and
the members inherited from System.Object, and the following statements
are permitted:
int i = int.MaxValue; // System.Int32.MaxValue constant
string s = i.ToString(); // System.Int32.ToString() instance method
string t = 123.ToString(); // System.Int32.ToString() instance method
The simple types differ from other struct types in that they permit
certain additional operations:
Most simple types permit values to be created by writing literals
(ยง1.16.4). For example, 123 is a literal of type int and 'a' is a
literal of type char. C# makes no provision for literals of struct
types in general, and nondefault values of other struct types are
ultimately always created through instance constructors of those
struct types.
As the spec explains simple types have some super powers like the ability to be const, a special literal syntax that could be used instead of new, and the capacity to be computed at compilation time (2+2 is actually written as 4 in the final MSIL stream)
But methods (as well as operators) aren't a special super powers and all structs could have them.
The specification (for C# 4.0, my copy paste is from an earlier version) could be downloaded from the microsoft website : C# Language Specification 4.0
Eric Lippert's recent article Inheritance and Representation explains.(Spoiler: You are confusing inheritance and representation.)
Not sure why you claim that the integer i, the character 'c' and the integer 1 are not objects. They are.
In C# all primitive types are actually structures.
So that you can use them!
It's convenient to be able to do so, so you can.
Now, in order to do so, primitives can be treated as structs. E.g. a 32-bit integer can be processed as a 32-bit integer, but it can also be processed as public struct Int32 : IComparable, IFormattable, IConvertible, IComparable<int>, IEquatable<int>. We mostly get the best of both worlds.
in java it is possible to give an enum a constructor as well as member variables and functions.
i was wondering if something like this is possible in c# enums as well. if so, how?
thanks a lot!
The only way to do something similar to this is to use extension methods, which can make it appear as though the enumeration has member methods.
Other than that, you could create a companion struct type to your enumeration that has a property for the enumeration value and then adds additional properties and methods to support that value.
It is not. In Java, enumerations are a class while in C#, an enumeration is just syntactic sugar wrapping a primitive type.
Enums are strongly typed constants. They are essentially unique types that allow you to assign symbolic names to integral values. In the C# tradition, they are strongly typed, meaning that an enum of one type may not be implicitly assigned to an enum of another type even though the underlying value of their members are the same. Along the same lines, integral types and enums are not implicitly interchangable. All assignments between different enum types and integral types require an explicit cast.
You can't use member variables or constructors in an enum. Maybe what you are looking for is an struct.
A struct type is a value type that can contain constructors, constants, fields, methods, properties, indexers, operators, events, and nested types. The declaration of a struct takes the following form:
You could imitate the Java TypeSafe enum pattern (what was so common in Java before enum was introduced in Java 5 to address it):
See Item 21 here (warning, PDF link) for a description.
You would do this if the object functionality was more important than the switch functionality, since in C# you can get the type saftey without it (which you couldn't in Java before 5).
One thing I've always loved to do is to use the Description attribute on my enums so I can store 3 values of my enum easily
Public Enum States
{
[Description("Florida")]
FL = 124
}
And then I had a class that easily reads to/from the description attribute so I could store a whole database code table in an enum file. Aside from all the posters bringing up extension methods you could use attributes to drive log with your enum classes.
You would still need to leverage another class to actually do something with the enum but you could use attributes to add more depth to your enum instead of just having the key/value pair that it basically is.
Not directly but you can use Extension methods to provide similar functionality
This is not possible in C#. Enums can only have name / value members.
As far as I am aware, no you can't in C#. Although why would you want too? Seems a bit of an odd thing to attach variables and functions too!
You can define extension methods for enum types, but you can't add state to enums, since enums are represented as simple integer types internally, and there'd be nowhere to store the state.