How should I encapsulate this multi-dimensional enum? - c#

In my application I've got some information that can be one of a small set of values - so I'd like to use an enum to hold it, ensuring valid values through type-safety at compile time:
public enum Something { A1, A2, A3, B1, B2, C1 };
These enums represent multi-dimensional data (they have a letter and a number in the example above), so I'd like to be able to get the value associated with them, e.g.
Something example = Something.A1;
// Now I want to be able to query the values for example:
example.Letter; // I want to get "A"
example.Number; // "1"I want to get 1
I've two possible solutions, neither of them feel very 'clean', so I was interested in which people prefer, and why, or whether anyone has any better ideas.
Option 1:
Create a struct which wraps the enum, and provides properties on the wrapped data, e.g.
public struct SomethingWrapper
{
public Something Value { get; private set; }
public SomethingWrapper(Something val)
{
Value = val;
}
public string Letter
{
get
{
// switch on Value...
}
}
public int Number
{
get
{
// switch on Value...
}
}
}
Option 2:
Leave the enum as it is and create a static Helper class which provides static functions that get the values:
public static class SomethingHelper
{
public static string Letter(Something val)
{
// switch on val parameter
}
public static int Number(Something val)
{
// switch on val parameter
}
}
Which should I choose, and why? Or is there a better solution I've not thought of?

Third option: like the second option, but with extension methods:
public static class SomethingHelper
{
public static string Letter(this Something val)
{
// switch on val parameter
}
public static int Number(this Something val)
{
// switch on val parameter
}
}
Then you can do:
Something x = ...;
string letter = x.Letter();
It's unfortunate that there aren't extension properties, but such is life.
Alternatively, create your own pseudo enum: something like this:
public sealed class Something
{
public static Something A1 = new Something("A", 1);
public static Something A2 = ...;
private Something(string letter, int number)
{
Letter = letter;
Number = number;
}
public string Letter { get; private set; }
public int Number { get; private set; }
}

Why not just use two enums, and maybe define a struct that holds one of each?

Related

Set Data Annotation MaxLength w/ Variable?

I want to set the [MaxLength()] data annotation in my EF Core 7 entity with a variable. Here's my code.
public static class Constants
{
public static byte IdentifierMaxLength { get { return 46; } }
public static byte NameMaxLength { get { return 64; } }
public static ushort DescriptionMaxLength { get { return 1024; } }
public static ushort UsageMaxLength { get { return 1024; } }
}
public class TagEntity
{
private byte _maxIdentifierLength;
public Tag()
{
_maxIdentifierLength = Constants.IdentifierMaxLength;
}
[Required]
[MaxLength(_maxIdentifierLength)]
public string Identifier { get; set; }
}
// Or better yet:
[MaxLength(Constants.IdentifierMaxLength)]
I get this error instead:
An object reference is required for the non-static field, method, or property 'Tag._maxIdentifierLength'
Is this possible? If not, is there another way to go about this so I don't have to change these lengths in multiple places if they ever need to change?
Values provided to Attributes must be known at compile time. Constants are a good way of providing that guarantee.
Change your Constants class to have actual constants. In addition, you'll need/want to change the type to int to match the parameter for the attribute.
public static class Constants
{
public const int IdentifierMaxLength = 46;
}
Now you can do
[MaxLength(Constants.IdentifierMaxLength)]

Class designing in C#

I'm learning C# and currently we're looking into OOP concepts. We've been given this question and I'm struggling to understand some parts of it.
The gist of the question is this.
Define a class named Operator.
That class should implement following methods.
IsPositive - Receives an integer type value and returns true if it
is positive, false otherwise.
IsDayOfWeek - Receives a date time value and a week day name (E.g.
Saturday) and returns true if the value represents the given week day
name, false otherwise.
GetWords - Receives a text containing words (say paragraphs) and
returns a single dimension string array with all words. An empty
string array if there is no word available in the text.
It should be able to derive from Operator class and then create objects from the derived class.
Developers are allowed to use these methods from derived class for a given type. In other words, 1st method could be used when type = ‘N’ (number), 2nd methods could be used when type is ‘D’ (date) and 3rd method could be used when type is ‘S’ (string) given. Hence, the type should be provided when instantiating the object and it should be available throughout the class operations.
I have sufficient knowledge to write the methods but what I don't understand is the part I have bold-ed. What does it mean by some method can be used when some type is given and the type should be provided when instantiating the object and it should be available throughout the class? Are they talking about Properties?
I have given it a go. Below is my code.
public class Operator
{
private int _n;
private DateTime _d;
private string _s;
public DataProcessor(int n, DateTime d, string s)
{
this.N = n;
this.D = d;
this.S = s;
}
public int N
{
set { _n = value; }
}
public DateTime D
{
set { _d = value; }
}
public string S
{
set { _s = value; }
}
public bool IsPositive()
{
//method code goes here
return false;
}
public bool IsDayOfWeek()
{
//method code goes here
return false;
}
}
I'm not sure if I'm going the right way. Can somebody please shed some light on this?
This is how I read it:
public class Operator
{
public char TypeChar { get; set; }
public Operator(char operatorType) { this.TypeChar = operatorType; }
public bool IsPositive(int N)
{
if (TypeChar != 'N')
throw new Exception("Cannot call this method for this type of Operator");
// method implementation code
}
// same for the other methods
}
public NumericOperator : Operator
{
public NumericOperator() : base('N') {}
}

List which accept only few types

Does there exist in any System namespace in C# a container, which can accept only some types?
For example I want to create my list in which I'll have only objects with type Class1 and int:
//accept only type Class1 and int;
MYLIST lst = new MYLIST(typeof(Class1), typeof(int));
lst.Add( 23 ); // OK
lst.Add( new Class1() ); // OK
lst.Add( "text" ); // wrong, not accepted type
Is something like that in .NET or I have to write it on my own? Thanks.
The C# type system does not allow you to express something like "either Class1 or int". Having said that, you can use overloads to get half of the way there:
class MyClass
{
private List<object> _items = new List<object>();
public void Add(int value) { _items.Add(value); }
public void Add(Class1 value) { _items.Add(value); }
...
}
The real tricky question is how you get things out, rather than how you put things in. There are several possibilities: get everything out as object (by implementing IEnumerable<object>), and maybe special methods like GetInt(int index) and GetClass1(int index).
The answer is NO, there is NO such list in C# and for VERY GOOD reason.
You could make a wrapper, but i'd advise against it.
public class CustomListWrapper< T, F>
{
private readonly List<object> internalList;
public CustomListWrapper()
{
this.internalList = new List<object>();
}
public void Add(object item)
{
if(!(item is T || item is F))
throw new Exception();
this.Add(item);
}
}
PS: before the downvote, for how to get the object out...well this is why this is a fairly bad idea, but you'd have to do an "is" on the type you get out to be able to cast it to the proper type.
Again, not exactly sure why you would EVER need to do this.
No. You will have to create your own. You can implement ICollection or IEnumerable or IList or whatever. You have lots of flexibility here. But bottom line, the answer is no, no such collection exists that allows you to limit the types in the collection to certain types automatically.
You cannot achieve this in a direct way. The item type of a List<T> must be a base type common to all the types you want to add to the list.
You could have a List<object> or a wrapper around a List<object> of cause. However, you would have to check at runtime if the items added to it are of the correct types and you would have to cast the items that you retrieve from the list to the correct type.
If you want to store different types in the same list, a good option would be to create an interface that all of these types must implement
public interface ICommonInterface
{
int Number { get; }
string Text { get; }
}
public Class1 : ICommonInterface
{
public int Number { get; set; }
public string Text { get; set; }
public string AnAdditionalProperty { get; set; }
}
public NumberWrapper : ICommonInterface
{
public NumberWrapper (int number)
{
this.Number = number;
this.Text = number.ToString();
}
public int Number { get; private set; }
public string Text { get; private set; }
}
public TextWrapper : ICommonInterface
{
public TextWrapper (string text)
{
this.Text = text;
int i;
Int32.TryParse(text, out i);
this.Number = i;
}
public int Number { get; private set; }
public string Text { get; private set; }
}
Then you can declare your list as
List<ICommonInterface> lst = new List<ICommonInterface>();
lst.Add(new Class1());
lst.Add(new NumberWrapper(77));
lst.Add(new TextWrapper("hello"));
Console.WriteLine(lst[0].Text);
why not just wrap a List<>, and make two add methods, one that accepts int, another that accepts Class1

How to specify defaults for a plugin function in C#

I'm trying to implement a simple plugin system which will allow people to write the following:
[Plugin("A plugin function")]
public static int PluginFunction(int a, int b)
{
return a + b;
}
and then drop the DLL containing this function into a folder where it will be scanned by the application and show up as an available function at runtime. This all works fine, so far so good, the PluginAttribute class is what you would expect, just a description string for the function.
However, I'd like to allow the plugin writer to specify default values for the parameters. This is OK for values which are constant at compile time and then deduced via reflection, but I'd like a way to specify defaults for more complex types which will be created at runtime. Has anyone implemented something similar? The primary goal is to make it simple to implement plugin functions - I'm trying to avoid complex scaffolding but accept that my nice simple system is not going to cut it if I want this feature. I'm also happy to have some complexity in the application code which makes the system appear simple to the plugin writer.
Thanks,
Charlie.
Update:
I'm going with a combination of what's been suggested here, the closest is what Peter O. came up with - here's a version:
[Plugin("A plugin function")]
[Defaults(typeof(AdderDefaults))]
public static int Adder(int a, int b)
{
return a + b;
}
public static class AdderDefaults
{
public static int a { get { return 1; } }
public static int b { get { return 2; } }
}
[Plugin("Another plugin function")]
[Defaults(typeof(TexturizerDefaults))]
public static Bitmap Texturize(Bitmap source, Point offset)
{
return result;
}
public static class TexturizerDefaults
{
// no default for source parameter
public static Point offset { get { return new Point(16, 16); } }
}
This allows parameters to be skipped and specified by name. No compile time checking but that's OK - checking these at runtime is acceptable.
Maybe you can create an attribute which refers to a type
containing default values for the plugin. Example:
[PluginDefaults(typeof(MyPluginDefaults))]
The class MyPluginDefaults could then look like:
public class MyPluginDefaults {
int Parameter1 { // First parameter
get { return 0; } // default value for 'a'
}
int Parameter2 { // Second parameter
get { return 4; } // default value for 'b'
}
// Additional parameters would be called Parameter3, Parameter4, and so on.
}
There are lots of way to do that, the simpliest is to use a simple convention :
[Plugin("A plugin function")]
public static int PluginFunction(int a, int b)
{
return a + b;
}
public static object[] PluginFunctionDefaultArguments()
{
return new [] { 0, 0 };
}
Each time you find a function marked with PluginAttribute search for a function having the same name with the DefaultArguments sufix, no parameters and an object[] return type. Then call it and store the values somewhere. You should also support the default values to be specifed using the dedicated C#/VB syntax (it is found in the DefaultValue member for the parameter)
One way would be to have property Defaults for each of the classes. It returns an object that can be queried for the defaults, for example like this:
object[] pluginFunctionDefaults = FooPlugin.Defaults["PluginFunction"];
(Obviously, you wouldn't have code exactly like this in your application.)
And the declaration of the defaults could look like this:
class FooPlugin
{
static FooPlugin()
{
var bar = new Bar();
Defaults = new DefaultValues()
.Add(() => PluginFunction(42, 13))
.Add(() => AnotherFunction(bar));
}
public static DefaultValues Defaults { get; private set; }
// actual methods of the class
}
Using expressions like this means that the types of the defaults are checked at compile time. The DefaultValues class parses the expressions and stores the parameters. It could look something like this:
class DefaultValues
{
private readonly Dictionary<string, object[]> m_expressions =
new Dictionary<string, object[]>();
public DefaultValues Add<T>(Expression<Func<T>> func)
{
var methodCall = ((MethodCallExpression)func.Body);
var name = methodCall.Method.Name;
var arguments =
methodCall.Arguments
.Select(Evaluate)
.ToArray();
m_expressions.Add(name, arguments);
return this;
}
private static object Evaluate(Expression expression)
{
return Expression.Lambda<Func<object>>(
Expression.Convert(expression, typeof(object)))
.Compile()();
}
public object[] this[string methodName]
{
get { return m_expressions[methodName]; }
}
}

Public Enumeration with only string values

I'm always confused which kind of enumeration I should use. A hashtable, an enum, a struct a dictionary, an array (how oldschool), static strings...
Instead of using strings in my code I want to use a beautiful enum like so:
public enum MyConfigs
{
Configuration1,
Configuration2
}
Problem is that I don't always want to convert my enum toString() as I'm not interested in the index representation of the enum.
What is the best way to represent a public enumeration of string based values?
In the end I would love to end up with using MyConfigs.Configuration1 where needed in my code.
I prefer defining "grouped" constants as static members of a dummy static class, like so:
public static class FieldNames
{
public const string BRANCH_CODE = "_frsBranchCode";
public const string BATCH_ID = "_frsBatchId";
public const string OFFICE_TYPE = "_frsOfficeType";
}
But of course they are not "enumerable" directly, so you can't foreach over them unless you provide a static array too:
public static string[] AllFieldNames
{
get
{
return new string[]
{
FieldNames.BRANCH_CODE,
FieldNames.BATCH_ID,
FieldNames.OFFICE_TYPE
};
}
}
public static class MyConfigs
{
public const string Configuration1 = "foo",
Configuration2 = "bar"
}
This is then pretty-much identical to how enums are implemented (ignoring the whole "it must be an integer" thing).
Type-safe enum pattern?
public class StringEnum
{
#region Enum Values
public static readonly StringEnum ValueOne = new StringEnum("Value One");
public static readonly StringEnum ValueTwo = new StringEnum("Value Two");
#endregion
#region Enum Functionality
public readonly string Value;
private StringEnum(string value)
{
Value = value;
}
public override string ToString()
{
return value;
}
#endregion
}
You can use this like:
private void Foo(StringEnum enumVal)
{
return "String value: " + enumVal;
}
If you never need to pass these values around in a type-safe manner to methods etc. then it is probably best to just stick with a constants file.

Categories