So I'm playing around a bit with the possibilities of modules for an application I'm building and I'd like to version them.
These modules which are dlls implement an interface with a property for the version of this module. The format should be "Major.Minor.Build".
If I create a property of type String, the possibility of a version like "Major.Minor" or "Major.Minor.Build.Revision" exists. I want to prevent that.
So I had the idea of a struct like Double but with a third digit. My question is now, is this even possible and if yes, how can I implement something like this?
In the class it should look like this:
public class MyModuleContext : IModuleContext
{
public ModuleVersion Version { get; set; } = 1.0.0;
// more interface things ...
}
Thanks for your help :)
Just create a class that meets your needs:
public class Version: IVersion
{
public int Major { get; }
public int Minor { get; }
public int Build { get; }
public override string ToString =>
$”{Major}.{Minor}.{Build}”
public Version(int major, int minor, int build)
{
//omitted argument validation
Major = major;
Minor = minor;
Build = build;
}
}
If you are mainly going to be passing IVersion references around, you are better off implementing this as a reference type or you’ll be boxing the value type all over the place.
It’s up to you if you want to implement value equality semantics, comparison logic, etc. It’s all pretty trivial.
Related
I have written an attribute class which I later used for sorting properties.
[AttributeUsage(AttributeTargets.Property)]
class OrderAttribute : Attribute
{
internal OrderAttribute(int order)
{
Order = order;
}
public int Order { get; private set; }
}
I want this to be unique for class properties, e.g.
Valid scenario
[Order(1)]
public string Tier3 { get; set; }
[Order(2)]
public string Tier4 { get; set; }
Invalid Scenario since value "1" is repeated.
[Order(1)]
public string Tier3 { get; set; }
[Order(1)]
public string Tier4 { get; set; }
PS: Attribute values can be repeated for different class properties but not in same. How can I achieve this?
Although attribute values can be repeated, there's no easy way supported to make sure they are unique (they are run time only), you would need to check when actually sorting as Johnathan has already mentioned. There are ways around this, but is it worth it in the long run? A few options I can think of are:
Hook into the actual build process, create a build task that uses reflection to check and fail if needed.
Run a post-build (post build event) step that loads your dll and reflects on those attribute types.
Create a possible rule that will check for uniqueness.
There may be other ways, but these are the one's I could think of at the moment.
This question already has answers here:
Is Int32.ToString() culture-specific?
(7 answers)
Closed 7 years ago.
Ok i am going through Saplo Api C# project. It stump me when i saw these code:
public class Helper
{
private static int _currentId;
public static int GetCurrentId()
{
return _currentId;
}
public static int GetNextId()
{
return ++_currentId;
}
}
[DataContract]
internal class RequestBase<T>
{
public RequestBase()
{
ID = Helper.GetNextId().ToString(CultureInfo.InvariantCulture);
}
public RequestBase(string method, T #params)
: this()
{
Method = method;
Parameters = #params;
}
[DataMember(Name = "id")]
public string ID { get; private set; }
[DataMember(Name = "method")]
public string Method { get; set; }
[DataMember(Name = "params")]
public T Parameters { get; set; }
}
So if you look at the constructor for RequestBase.... public RequestBase()! you will see Helper.GetNextId() this only return an int why bother using CultureInfo.InvariantCulture i dont understand why a simple ToString inst good enough to do the job or what, isnt this is just more overhead?
When it comes to integers, there is currently no recognized, official culture that would affect how Int32.ToString() behaves. It will always create an identical string.
However, that does not mean that a custom culture might not interpret the results differently. Resharper and other code style tools typically recommend using a culture to maintain consistency.
It is worth noting, when travelling outside of integers, cultures absolutely make a difference. For instance, in EN-US, commas are used for thousands separation and periods are used to represent the decimal point. On the other hand, in EN-GB it's the opposite. Keeping consistency between value types could certainly be viewed as a good habit.
That said, in this case, yes, providing CultureInfo for integers is probably unnecessary "overhead", unless you prefer to keep consistency in your codebase.
In this case it doesn't seem necessary. I know plugins like ReSharper and StyleCop will complain(show a warning) about an empty ToString() unless you tell them not to. It's possible one of these plugins was used when writing this code.
Generally CultureInfo.InvariantCulture is used when converting dates and decimal/currency values.
I want to write my enum with custom attributes, for example:
public enum SomeEnum: long
{
[SomeAttribute<MyClass1>]
Sms = 1,
[SomeAttribute<MyClass2>]
Email = 2
}
but attributes doesn't support generics. Well, the most similar solution is:
public enum SomeEnum: long
{
[SomeAttribute(typeof(MyClass1))]
Sms = 1,
[SomeAttribute(typeof(MyClass2))]
Email = 2
}
And here is problem: I want Class1 to be inherited from ICustomInterface, so with generics I can write constraint:
[AttributeUsage(AttributeTargets.All)]
class SomeAttribute<T> : Attribute where T: ICustomInterface
{
}
but attributes doesn't support generics.
so finally question is: how can I check in compile time (like T constraints) that type is implementing some interface?
Very simple to your final question:
so finally question is: how can I check in compile time (like T
constraints) that type is implementing some interface?
You can not do that.
But you can check it at runtime, with some reflection methods like:
Type.IsAssignableFrom
While i've had similar problems you won't get compile time checking for this.
For now this:
public class SomeAttribute : Attribute
{
public SomeAttribute(Type given)
{
Given = given;
Required = typeof (INotifyDataErrorInfo);
}
public Type Given { get; set; }
public Type Required { get; set; }
public bool Valid()
{
return Required.IsAssignableFrom(Given);
}
}
public enum TestEnum
{
[Some(typeof(string))]
Sms = 1,
[Some(typeof(string))]
Email = 2
}
Is far as you're gonna get sadly.
Though as far as i can recall, if you use PostSharp there is a way to invoke code dependant compile time checks if that's what you're after. That may not point out flaws visually in your IDE, but it still ensures that other devs have to ensure that a certain type is passed.
I am looking for an Attribute-written-code to specify the parameter range such as it works on a property. I need it on a method.
Analogy which exists (and works) for a property:
[Range(0,10)]
public int MyProperty{ get; set; }
Is there any analogy for a method? (below is my pseudocode):
[Range(0,10,"MyParameter")]
public void MyMethod(int MyParameter){...}
I know that there is the alternative
throw new ArgumentOutOfRangeException();
but I am asking for alternative in Attribute.
Any help?
The syntax would look a bit like this:
public void MyMethod([Range(0,10)] int myParameter)
{
...
}
And thankfully, the built-in RangeAttribute supports AttributeTargets.Parameter, so this will compile. However, whether or not this is enforced depends entirely on how this is used. You'll need some kind of validation framework that checks the parameter for a valid range. The .NET framework will not do this for you automatically on all method calls.
Existing solutions that allow this:
public void MyMethod([Range(0, 10)] int MyParameter) { ... }
I have a naming problem for some of my classes. I need to wrap some primitive .net types into a class like the following. There will be about 20 of such classes.
(The naming is crap, of course. Just for a demonstrative purpose)
public class Int32Single
{
public int Value { get; set; }
}
public class Int32Double
{
public int Value1 { get; set; }
public int Value2 { get; set; }
}
public class DoubleSingle
{
public double Value { get; set; }
}
I can't use a generic approach for this.
How should I name such wrapper classes, where each class name should provide the necessary information which primite types are wrapped and in which quantity?
It might also be possible that I have class that contains mixed primite types.
This doesn't seem like a very good idea at all. You have both the Tuple class and a standard array available, that both make more sense in any conceivable use case. However, that doesn't answer your question, so...
The most intuitive name for a wrapper class would follow the convention of {type-name}Wrapper, or for example, Int32Wrapper. In your case, the wrapped object is a primitive type, so makes sense to call the class a "Tuple". Since you want to specify the size of the Tuple in your class name, {primitive-type-name}{size}Tuple seems like the most intuitive naming convention but this causes several problems.
The natural language used to describe Tuples create ambiguity (such as Single and Double because they conflict with the Type names). (e.g. DoubleDouble is bad)
Integers are used in the naming of some primitive types so this could cause ambiguity. (e.g. Int322Tuple is bad).
We can't move the size to the beginning such as 2Int32Tuple because integers are not valid characters to begin a class name. So, There are two approaches that I think could work.
I think your best bet to get around these constraints, is to use a {primitive-type-name}{text-represented-size}Tuple convention. (e.g. Int32TwoTuple or DoubleTwoTuple). This convention expresses the contents of the wrapper class without ambiguity, so it seems like a good approach. In addition the name begins with the primitive type name, so, if you have a lot of these classes, it will be easier for your IntelliSense to fill in the correct class name, and it will alphabetically be listed next to the primitive type that is being wrapped.
Generics can help you out here:
public class WrapTwo<T>
{
public T Value1 { get; set; }
public T Value2 { get; set; }
}
public class WrapOne<T>
{
public T Value1 { get; set; }
}
And have you considered the Tuple class?
OneInt32, TwoInt32s, TwoDoubles? Doesn't sound great.
Tuples? http://www.dotnetperls.com/tuple
I don't very fond of Tuples or arrays, because both don't tell much about their purpose. Well, I use them. But mostly as internal members of classes, local variables, or with 3rd party/legacy code.
Back to naming. Compare:
Tuple<int,int> a = Tuple.Create(10,10);
Int32Double b = new Int32Double(15, 15);
WrapTwo<int> c = new WrapTwo<int>(20, 20);
With
Point a = new Point(10, 10);
Vertex b = new Vertex(15, 15);
One can argue, that 'a' is not good name for variable (and suggest to use 'pointA' instead). But I think it's pretty good in context of geometry application.
Not just type name and creation code looks obscure, but consider type fields names:
a.X = 20;
b.Value1 = 20;
So, I think you need some self-descriptive type in context of your application domain.