Constrain a string parameter to be a constant from a specific class - c#

This is probably an incredibly dumb question but: I have a function that takes in a string, and I want to make sure that the string is a constant from a specific class. Essentially the effect I'm looking for is what enums do:
enum MyEnum {...}
void doStuff(MyEnum constValue) {...}
Except with strings:
static class MyFakeStringEnum {
public const string Value1 = "value1";
public const string Value2 = "value2";
}
// Ideally:
void doStuff(MyFakeStringEnum constValue) {...}
// Reality:
void doStuff(string constValue) {...}
I know this can technically be achieved by doing some thing like
public static class MyFakeStringEnum {
public struct StringEnumValue {
public string Value { get; private set; }
public StringEnumValue(string v) { Value = v; }
}
public static readonly StringEnumValue Value1 = new StringEnumValue("value1");
public static readonly StringEnumValue Value2 = new StringEnumValue("value2");
}
void doStuff(MyFakeStringEnum.StringEnumValue constValue) {...}
But it feels kind of overkill to make an object for just storing one single value.
Is this something doable without the extra code layer and overhead?
Edit: While a enum can indeed be used for a string, I'd like to avoid it for several reasons:
The string values may not always be a 1:1 translation from the enum. If I have a space in there, different capitalization, a different character set/language, etc. I'd have to transform the enum in every function where I want to use it. It might not be a lot of overhead or a performance hit in any way, but it still should be avoided--especially when it means that I'm always mutating something that should be constant.
Even if I use a separate string array map to solve the above function, I would still have to access the translations instead of just being able to use the enum directly. A map would also mean having two sources for the same data.
I'm interested in this concept for different data types, ex. floats, ulongs, etc. that cannot be easily represented by enum names or stored as an enum value.
As for string -> enum, the point of using an enum in the first place for me is that I can rely on intellisense to give me a constant that exists; I don't want to wait until compile time or runtime to find out. Passing in an actual string would be duck typing and that's something I definitely don't want to do in a strongly typed language.

I would suggest you create an enum and parse the string value into an enum member.
You can use the Enum.Parse method to do that. It throws ArgumentException if the provided value is not a valid member.
using System;
class Program
{
enum MyEnum
{
FirstValue,
SecondValue,
ThirdValue,
FourthValue
}
public static void doStuff(string constValue)
{
var parsedValue = Enum.Parse(typeof(MyEnum), constValue);
Console.WriteLine($"Type: { parsedValue.GetType() }, value: { parsedValue }");
}
static void Main(string[] args)
{
doStuff("FirstValue"); // Runs
doStuff("FirstValuesss"); // Throws ArgumentException
}
}

Related

How to make value type a ref type?

I have a static double variable in a static class. When I create a specific class, I use the double variable as one of the args of the constructor. What would be the easiest way of manipulating field of the object by changing the variable in static class.
Code for clarity:
public static class Vars
{
public static double Double1 = 5.0;
}
public class ClassFoo
{
public double Field1;
public ClassFoo(double number)
{
Field1 = number;
}
}
class Program
{
static void Main(string[] args)
{
ClassFoo Foo = new ClassFoo(Vars.Double1);
Console.WriteLine(Foo.Field1 + " " + Vars.Double1); //5 5
Vars.Double1 = 0.0;
Console.WriteLine(Foo.Field1 + " " + Vars.Double1); //5 0
//Foo.Field1 need to be a reference to Vars.Double1
}
}
EDIT that goes beyond the question (no more answers needed, other solution found):
I change some values (fields) very often (at runtime, or at least i would like to change them at runtime) to look for one that is right for me. Implementing:
if(KeyDown)
variable++;
if(OtherKeyDown)
variable--;
Wasn't convenient enough. I just checked Visual Studio Debugger. It's not good (fast) enough. Have to pause, change and run code code again. Method i presented would be good if changed static variable would change field of the object.
In short: no, you can't do this... at least, not seamlessly.
As noted, this is generally considered to be A Bad Idea™. There is no reference encapsulation for value types, and no simple way to implement a seamless wrapper class to do it because you can't overload the assignment operators. You can use the techniques from the Nullable<T> type to get part-way there, but no further.
The big stumbling block is the assignment operator. For the Nullable type this is fine. Since it is non-referencing (new values are distinct), an implicit conversion operator is sufficient. For a referencing type you need to be able to overload the assignment operator to ensure that assignment changes the contained data instead of replacing the wrapper instance.
About the closest you can get to full reference is something like this:
public class Refable<T> where T : struct
{
public T Value { get; set; }
public Refable(T initial = default(T))
{
Value = initial;
}
public static implicit operator T(Refable<T> self)
{
return self.Value;
}
}
This will hold a value of the specific type, will automatically convert to that type where applicable (Refable<double> will implicitly convert to double when required for instance), but all assignments must be done by referencing the Value property.
Example usage:
Refable<double> rd1 = new Refable<double>(1.5);
Refable<double> rd2 = d1;
// get initial value
double d1 = rd1;
// set value to 2.5 via second reference
rd2.Value = 2.5;
// get current value
double d2 = rd1;
// Output should be: 1.5, 2.5
Console.WriteLine("{0}, {1}", d1, d2);
What you really want to do is have Vars be a regular class, not a static class. For all methods and classes that need to deal with the variables contained in Vars, you can pass in a reference to that Vars instance.
Here is a very simple example program that illustrates the above. Note that you could probably do a lot to improve the design of your program, but this will at least get you going in the right direction, and away from trying to bend the language to do things it can't or shouldn't do.
public class SharedVars {
public static double Foo = 0.0;
}
public class ClassFoo {
private SharedVars mySharedVars;
public ClassFoo(SharedVars sharedVars) {
// save a reference to the shared variables container class for future use
mySharedVars = sharedVars;
}
// here's an example use
public void ProcessKeyDown() {
mySharedVars.foo++;
}
}
class Program {
static void Main(string[] args) {
SharedVars sharedVars = new SharedVars();
ClassFoo foo = new ClassFoo(sharedVars);
// ... some stuff happens ...
if(KeyDown)
foo.ProcessKeyDown();
}
}

How to use multi properties in class that contain one variable?

I have class named "config" that have private string variable named "param".
I need to get from "config" class "param" variable sometimes as int type sometimes as bool type or string.
As I understand I need create 3 properties in config class,each property have to convert type, as follow:
The first property converts string to int, the second converts string to bool, the third property gets me the string value.
The class should look something like this:
class Config
{
private string param;
public int ParamAsInt
{
get
{
return int.Parse(param);
}
}
public bool ParamAsBool
{
get
{
return bool.Parse(param);
}
}
public string ParamAsString
{
get
{
return param;
}
}
}
But I don't know how can those properties be used in accordance to the variable type that I want to get out of class.
This code won't compile - int and such are reserved keywords and cannot be used as identifiers. You can either try naming your properties something like Int32Value, StringValue, etc., or try this:
public static implicit operator bool (Config config)
{
return bool.Parse(config.param);
}
public static implicit operator int (Config config)
{
return int.Parse(config.param);
}
This will allow for much cleaner code:
Config c = GetConfig("foo");
var isFeatureEnabled = false || c;
var spacing = 23 + GetConfig("bar");
You forgot to give your properties names. How would you expect to reference them? Something like this:
class Config
{
private string param;
public int ParamAsInt
{
get
{
return int.Parse(param);
}
}
public bool ParamAsBool
{
get
{
return bool.Parse(param);
}
}
public string ParamAsString
{
get
{
return param;
}
}
}
Note that I also fixed the casing in your calls to .Parse(). C# is case-sensitive. I also replaced the call to bool.TryParse() with bool.Parse(). The former (when used correctly, which this wasn't because it was missing a parameter) will only tell you if it is a bool, it won't tell you what value the bool actually has. (For example, bool.TryParse('false' out someBool) will return true.)
Of course, this code is a bit dangerous. You'll want to start with some more defensive programming to check those values. Basically, look up TryParse() and how to use it correctly. Something like this, for example:
public int ParamAsInt
{
get
{
var tmp = default(int);
if (int.TryParse(param, out tmp))
return tmp;
else
// do something else? throw a specific exception?
}
}
Additionally, what is the purpose of this code? It seems like a very rushed and poor design. For any given value of param (how is that even being set, by the way?) this just sort of randomly tries to expose typed properties for it. If you guess the correct one, you're still left with others that will throw exceptions. Surely there's a much cleaner way to accomplish what you're trying to do. So what are you trying to do?

Enum of GUID's/Guid interop

I'm doing some interop and need to pass some GUID's. Is there a way to add a GUID attribute to an enum value and when it is marshalled it has the appropriate value?
Basically I'm trying to convert the code
#if !defined( STATIC_KSDATAFORMAT_SUBTYPE_PCM )
#define STATIC_KSDATAFORMAT_SUBTYPE_PCM\
DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_PCM)
DEFINE_GUIDSTRUCT("00000001-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_PCM);
#define KSDATAFORMAT_SUBTYPE_PCM DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_PCM)
#endif
(and several other similar ones)
and use them in an enum so I can specify the appropriate subtype format easily. Obviously I could probably just use a dictionary or some other similar method but I would like to make it as transparent as possible.
It would be nice to do something like
enum MyGuids : Guid
{
Guid1 = GUID("...") or just "..."
}
I can use a class/struct instead
static class MyGuids
{
public static Guid flag1 = new Guid("9ED54F84-A89D-4fcd-A854-44251E925F09");
}
But the only problem here is there is no way to relate the Guid in unmanaged structure to this class. It's specified as Guid and if I replaced it with MyGuids then it won't be a Guid any more. e.g., I lose type safety since any guid can end up in the field and not just the ones from MyGuid.
Any ideas?
Guids are structures in .NET, they are too large to fit in a simple value type by a factor of two. Sounds to me that you need a structure member initialized. That's going to need an assignment statement in your code. The const will work just fine for this. There is otherwise no way to get the compiler to do it automatically.
var sound = new foo();
sound.waveFormat = MyGuids.flag1;
// etc..
How about something like this?
void Main()
{
var dog = MyValues.Dog.ToId();
var cat = MyValues.Cat.ToId();
var bird = MyValues.Bird.ToId();
}
public enum MyValues
{
Dog,
Cat,
Bird
}
public static class Functions
{
public static Guid ToId(this MyValues value)
{
switch (value)
{
case MyValues.Dog:
return Guid.Parse("6d139d6a-2bfa-466d-a9a5-c6e82f9abf51");
case MyValues.Cat:
return Guid.Parse("AA139d6a-2bfa-466d-a9a5-c6e82f9abf51");
case MyValues.Bird:
return Guid.Parse("BB139d6a-2bfa-466d-a9a5-c6e82f9abf51");
default:
throw new InvalidDataException();
}
}
}

C# Attributes - Arrays or Duplicates?

I am creating a network chat client in C# as a side project. In addition to simple text messages, I also have slash-prefixed commands that can be entered into the input TextBox. I used a modular approach by creating an enum that contains all the various commands, and then decorating those commands with attributes.
The attributes specify what slash-prefixed command can be entered to trigger the command, as well as any aliases to the primary command identifier and the command's usage.
Example:
public enum CommandType : byte
{
[PrimaryIdentifier("file"),
AdditionalIdentifier("f"),
CommandUsage("[<recipient>] [<filelocation>]")]
FileTransferInitiation,
[PrimaryIdentifier("accept"),
AdditionalIdentifier("a")]
AcceptFileTransfer,
// ...
}
My problem arises when I try to allow multiple aliases to the primary command. I have attempted this two ways: by allowing duplicates of the AdditionalIdentifier attribute, or by making the constructor argument in AdditionalIdentifier a params string[].
With the former, I implemented it by decorating the attribute class with AttributeUsage and setting AllowMultiple to true. While this does indeed achieve what I'm looking for, I'm feeling like it could get really noisy really fast to have several lines of aliases, in addition to the other attributes.
The latter also works, however, it generates the compiler warning CS3016, and says that that approach is not CLS-compliant. Obviously, this doesn't necessarily stop me from still using it, but I've learned to always treat warnings as errors.
My actual question is should I ignore my objections with duplicates and just go ahead and use them, or is there some other solution that could be used?
Thank you.
You could also use "params string[] aliases" in the constructor to allow a variable argument list:
[AttributeUsage(AttributeTargets.Method)]
class TestAttribute : Attribute
{
public TestAttribute(params string[] aliases)
{
allowedAliases = aliases;
}
public string[] allowedAliases { get; set; }
}
This would allow you to do:
[Test("test1", "test2", "test3")]
static void Main(string[] args)
Personally I would go with the AllowMultiple approach: I don't think the "noise" is going to be that much of a problem unless you really have truckloads of identifiers for each command. But if you don't like that and want to stay CLS-compliant, one other solution would be to provide overloaded constructors for AdditionalIdentifierAttribute:
public AdditionalIdentifierAttribute(string id) { ... }
public AdditionalIdentifierAttribute(string id1, string id2) { ... }
public AdditionalIdentifierAttribute(string id1, string id2, string id3) { ... }
The downside is that this does limit you to a predetermined number of identifiers.
That said, CLS compliance is really only a major consideration if you are building a library that others are likely to use (and specifically from other languages). If this type or the library is internal to your application, then it's reasonable to ignore CLS compliance warnings.
EDIT: Thinking further about this, you have quite a lot of attributes on those enums. You might want to consider creating an abstract Command class instead, and exposing the identifiers, usage, etc. as properties of that class; then derive concrete types of Command which return the appropriate values from those properties. This potentially also allows you to move the handling logic into those Command objects rather than switching on the enum value.
Why not have a single attribute with multiple properties? Have the property for the alias take a comma-separated list. This is the approach they take in MVC for things like the AuthorizeAttribute for Roles. Internally, the property parses the string into an array for ease of use in the attribute class, but it allows you an easy way to set up your configuration.
public class IdentifierAttribute
{
public string Name { get; set; }
public string Usage { get; set; }
private string[] aliasArray;
private string aliases;
public string Aliases
{
get { return this.aliases; }
set
{
this.aliases = value;
this.aliasArray = value.Split(',').Trim();
}
}
}
Then use it like:
public enum CommandType : byte
{
[Identifer( Name = "file", Aliases = "f", Usage = "..." )]
FileTransferType,
...
}
Yet another approach would be to have the attribute take an array of strings as a constructor parameter - that way, you get the compiler to parse the array for you (at the expense of a little more goop when applying the attribute) thus:
[Identifiers(new string[] {"Bill", "Ben", "Ted"})]
A quick 'n dirty example of implementing & using such a technique looks like this:
using System;
using System.Collections.ObjectModel;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
SomeClass.TellMeAboutYourself();
}
}
public class Identifiers : Attribute
{
private string[] names;
public Identifiers(string[] someNames)
{
names = someNames;
}
public ReadOnlyCollection<string> Names { get { return new ReadOnlyCollection<string>(names); } }
}
[Identifiers(new string[] {"Bill", "Ben", "Ted"})]
static class SomeClass
{
public static void TellMeAboutYourself()
{
Identifiers theAttribute = (Identifiers)Attribute.GetCustomAttribute(typeof(SomeClass), typeof(Identifiers));
foreach (var s in theAttribute.Names)
{
Console.WriteLine(s);
}
}
}
}

How to implement C# enum for enumerated char(1) database field?

OK, so I have a database field of type char(1) that has a small number of possible state codes (e.g. 'F'= Failure, 'U'=Unknown, etc.). I'd like to have a C# enum class that corresponds to these states. I can do:
public enum StatusCode : byte {
Unknown = (byte) 'U',
Failure = (byte) 'F',
// etc.
}
So far so good. But in the DataTable returned from the database, the column values are System.Data.SqlTypes.SqlString instances. There are obviously some issues converting from a C# string (or even a C# char) to a C# byte (since C# char is really a UTF-16 codepoint). But in this case I know the values are constrained to a small set, and the code should throw an exception if a value outside this set comes through.
With that in mind, what's the best way of doing this? Is it safe to cast from a SqlString to a byte? Would Convert.ToByte() be better? Would it be better to simply use a switch/case construct to crosswalk the values into the enum?
I'm looking for the "best" way to do this, not only in terms of getting the right results but also for code clarity. I suppose I could also just use some constants like
public const char UnknownStatus = 'U';
public const char FailureStatus = 'F';
But I'd rather use an enum if possible. Any thoughts?
Edit: To clarify what I want do do with this, I'm expecting to use these values frequently throughout my code. For example, I want to be able to do things like:
public void DoSomething(StatusCode currentStatus) {
if(currentStatus == StatusCode.Failure) {
throw new SomeException();
}
switch(currentStatus) {
case StatusCode.Unknown:
// do something
break;
}
}
And so forth. I particularly want to avoid things like:
public void DoSomething(char currentStatus) {
if(currentStatus == 'F') {
// do something
}
}
Since in this case I'm using what amounts to "magic numbers" all over the place. In particular, this would make migrating to some other state-flagging system virtually impossible. Does that make sense?
Maybe a "constant" object?
public sealed class StatusCode {
private char value;
public static readonly StatusCode Unknown = new StatusCode('U');
public static readonly StatusCode Failure = new StatusCode('F');
private StatusCode(char v) {
value = v;
}
public override string ToString() {
return value.ToString();
}
}
Then, later in your code, you could use it like an enum: StatusCode.Unknown. You could also provide an internal method to 'parse' a received value into an object of StatusCode.
Skip to edit Have you tried this (which doesn't work as you've checked and commented):
public enum StatusCode : char
{
Failure = 'F',
Unknown = 'U',
...
}
EDIT - correct solution
or this (maybe even try with a struct):
public sealed class StatusCode
{
public static readonly char Failure = 'F';
public static readonly char Unknown = 'U';
...
public char Value { get; set; }
}
your code you provided would work like this:
public void DoSomething(StatusCode currentStatus) {
if(currentStatus.Value == StatusCode.Failure) {
throw new SomeException();
}
switch(currentStatus.Value) {
case StatusCode.Unknown:
// do something
break;
}
}
If you don't like to use Value property you can always implement implicit equality operator between StatusCode and char types. In that case, your code wouldn't change a bit.
If you're on .NET 2.0 and higher, you could implement this using a generic dictionary:
Dictionary<char,string> statusCode = new Dictionary<char,string>();
statusCode.Add('U', "Unknown");
statusCode.Add('F', "Failure");
or alternatively:
Dictionary<char,StatusCode> statusCode = new Dictionary<char,StatusCode>();
statusCode.Add('U', StatusCode.Unknown);
statusCode.Add('F', StatusCode.Failure);
and you could access the string representation for a given code like so:
string value = statusCode['A'];
or
StatusCode myCode = statusCode['A'];
and so on. You would have to fill that dictionary from the database values, or from some kind of a config file or something.
Marc
Would something like this work for you?
public Enum StatusCode : int{
[StringValue("U")]
Unknown =0,
[StringValue["F"]
Failuer=1
}
If you have a table called StatusCode which includes an integer primary key then you could use that as your identifier as well as hook it into your logic. And in that case, the enum would be the best thing to use. Though i'm not sure if this is feasible for you.
One option is to setup your enum with identical names to the values in your database, such as:
enum StatusCode
{
/// <summary>Unknown</summary>
U = 0,
/// <summary>Failure</summary>
F,
/// <summary>Etc</summary>
E
}
Then use a static method to convert char values to an enumerated value
private StatusCode CharToEnum(string statusCodeChar)
{
foreach (FieldInfo fi in typeof(StatusCode).GetFields())
{
if (fi.Name == statusCodeChar) return (StatusCode)fi.GetValue(null);
}
return StatusCode.U;
}
Short and sweet my man.. Does everything you need it to. You shouldn't need to use enum because you don't need it to assign an internal value to your possible states, you already know the values to your states.
public sealed class StatusCode
{
public const string Unknown= "U";
public const string Failure= "F";
public const string Success= "S";
}

Categories