How to convert from string to string constant in struct? - c#

So I have this struct:
public struct PurchaseOrderStatus {
public const string Open = "Open", Received = "Received";
}
How do I convert if I have the following:
string status = "Open";
To:
PurchaseOrderStatus.Open;
By Convert, I mean, how do I do this:
PurchaseOrderStatus POS;
String status = "Open";
POS = status;

I would suggest using "smart enums" here:
public sealed class PurchaseOrderStatus
{
public static readonly PurchaseOrderStatus Open =
new PurchaseOrderStatus("Open");
public static readonly PurchaseOrderStatus Received =
new PurchaseOrderStatus("Received");
private readonly string text;
public string Text { get { return value; } }
private PurchaseOrderStatus(string text)
{
this.text = text;
}
}
You can store arbitrary information here, including text which wouldn't be valid identifiers (so long as it doesn't change, of course). It's still strongly typed (unlike your strings) and you can give other behaviour to it. You can even create subclasses if you remove the sealed modifier and add the subclasses as nested classes so they still have access to the private constructor.
Oh, and there's a genuinely limited set of values (the ones you've defined and null) unlike with regular enums.
The only downside is that you can't switch on it.

Related

c# is there a DebuggerDisplay equivalent to format class members?

The DebuggerDisplay attribute allows to show a custom "value" or interpretation for entire class. This is good, but is there a possibility to force also displaying a standard type member (ie. UInt32) to a hexadecimal value?
There are 2 reasons I want this
some of my members has meaning in hex only (addresses, bit masks)
the hex formatting is global in C# IDE so I have to toggle manually quite often
[DebuggerDisplay("{_value,h}")]
public abstract class DataField
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private UInt32 _value;
// display this member in debugger permanent as HEX
public UInt32 ConstMask { get; set; }
}
One option I see is to declare ConstMask as a class and apply DebuggerDisplay formatting as well, but this will affect my performances and I guess is not a good option to do that just for debug purposes.
Thanks in advance for hints,
When you need more control/code to format your debugger display, you can use nq and the name of a property used to return the string. Like this:
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public abstract class DataField
{
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private UInt32 _value;
// display this member in debugger permanent as HEX
public UInt32 ConstMask { get; set; }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string DebuggerDisplay =>
$"{this.GetType().Name} 0x{this._value:X8}";
}
You are looking for the DebuggerTypeProxyAttribute. This attribute allows you to define a type which can be expanded to show all of the properties.
[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable : Hashtable
{
private const string TestString = "This should not appear in the debug window.";
internal class HashtableDebugView
{
private Hashtable hashtable;
public const string TestString = "This should appear in the debug window.";
public HashtableDebugView(Hashtable hashtable)
{
this.hashtable = hashtable;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePairs[] Keys
{
get
{
KeyValuePairs[] keys = new KeyValuePairs[hashtable.Count];
int i = 0;
foreach(object key in hashtable.Keys)
{
keys[i] = new KeyValuePairs(hashtable, key, hashtable[key]);
i++;
}
return keys;
}
}
}
}

Get private string from different class

I need to get a private string from a class, and count the frequency of words in the string.
the counting is the easy part... the bit I am struggling with is getting the string from the second class.
Heres what I am trying to get
public class GetString
{
private string myText = "this is the string that i need to get"
private string text;
public GetString()
{
text = myText
}
any and all help would be very much appreciated. I am also told I cannot edit this class
You have three options in my view:
You can make myText public.
You can return myText from another public member, preferably a property.
You can access the value via reflection (see: How to get the value of private field in C#?).
It seems that your getString class (by the way - bad naming a class with lowercase letter) contains a text property. If this property is public you can use it to get the string. If it is not public, there might be a method that exposes it. Your code is not complete, so it cannot be said for certain.
If there are no public properties or methods that expose the string, then the only way to get is through reflection
This seems rather fundemental, you have nothing in your getString class returning the string. Try something like
public class getString
{
private string myText = "this is the string that i need to get"
public String getString()
{
return myText
}
getString a = new getString();
String hiddenString = a.getString();
You cannot use the constructor for this purpose. Try this:
public class Foo
{
private string myText = "this is the string that i need to get";
public Foo()
{
}
public String GetString()
{
return this.myText;
}
}
Every method should either have the void keyword or the return type, which is in your case a String.
Use Properties (property is a member that provides a flexible mechanism to read, write, or compute the value of a private field.):
public string MyText
{
get { return myText; }
private set { myText = value; }
}
To follow on from #Petrichor, you could also potentially use interfaces:
public interface IHasText
{
string GetPrivateText();
}
public class GetString : IHasText
{
private string myText = "this is the string that i need to get";
string IHasText.GetPrivateText()
{
return myText;
}
}
var val = new GetString();
var asInterface = (IHasText)val;
string text = asInterface.GetPrivateText();

Getting CS0843 (backing field must be assigned) when calling constructor of struct

I am trying to replicate .NET's Color struct, which lets you call colors using Color.Black, Color.White etc. Here's my code:
struct Material
{
public string FilePath { get; set; }
public Material(string filepath) { FilePath = filepath; }
public static Material Sand
{
get
{
return new Material("images/sand");
}
}
public static Material Conrete
{
get
{
return new Material("images/conrete");
}
}
}
I'm getting an error saying I cannot use a constructor in a struct. I am effectively copying from the .NET source code (Color.cs) and this is how it does it, although it doesn't use a constructor. The static properties do return a new Material() however.
Full error message appearing on constructor CS0843:
backing field for automatically implemented property must be fully assigned before it is returned to the caller
You can simply "chain" this(), as in:
public Material(string filepath)
: this()
{
FilePath = filepath;
}
and this is the most common solution.
Of course you can do the same in other ways:
public Material(string filepath)
{
this = default(Material);
FilePath = filepath;
}
and
public Material(string filepath)
{
this = new Material { FilePath = filepath, };
}
and so on.
You CAN have a constructor, just not one with zero arguments.
However, isn't it clearer to write
new Material { FilePath = "images/concrete" }
instead of
new Material("images/concrete");
A custom constructor can always be bypassed by invoking the framework-provided parameterless constructor, so it can't be relied on for setting up invariants. And fields and properties can be set using member-initialization syntax. So struct constructors aren't terribly useful.

C#: Initialising member variables to be exposed via properties

I have just written a small piece of code and it struck me that I am not sure what method of initialisation is best practice when it comes to initialising my member variables which will be exposed and used via properties. Which is the best way to initialise my member variables out of the two examples below and more importantly why?
Example 1:
private string m_connectionString = ConfigurationManager.ConnectionStrings["ApplicationDefault"].ConnectionString;
private string m_providerName = ConfigurationManager.ConnectionStrings["ApplicationDefault"].ProviderName;
public string ConnectionString
{
get { return m_connectionString; }
set { m_connectionString = value; }
}
public string ProviderName
{
get { return m_providerName; }
set { m_providerName = value; }
}
public EntityClusterRefreshServiceDatabaseWorker()
{
}
Example 2:
private string m_connectionString;
private string m_providerName;
public string ConnectionString
{
get { return m_connectionString; }
set { m_connectionString = value; }
}
public string ProviderName
{
get { return m_providerName; }
set { m_providerName = value; }
}
public EntityClusterRefreshServiceDatabaseWorker()
{
ConnectionString = ConfigurationManager.ConnectionStrings["ApplicationDefault"].ConnectionString;
ProviderName = ConfigurationManager.ConnectionStrings["ApplicationDefault"].ProviderName;
}
NOTE: Assume that I am not using these variables in a static context.
It really doesn't matter which of those you use, except in the very odd situation where a base class constructor calls an overridden member, in which case the timing would change: instance variable initializers are run before the base class constructor call, whereas obviously the constructor body is executed afterwards.
In the latter case, you can make your code a lot simpler though using automatically implemented properties:
public string ConnectionString { get; set; }
public string ProviderName { get; set; }
public EntityClusterRefreshServiceDatabaseWorker()
{
// Code as before
ConnectionString = ...;
ProviderName = ...;
}
You can't do this with the first form, as automatically implemented properties don't have any way of specifying an initial value.
(You may also want to consider making the setters private, but that's a separate concern.)
You are essentially doing the same thing but writing it in a different form.
I always prefer (and use) the second aprroach because I don't like methods being executed in the middle of nowhere. It's better to split things. Attributes are declared on class body and initialized on class constructor.
As long as the connection strings are not supposed to be changed, you can initialize them as static readonly:
private readonly static string m_connectionString = ConfigurationManager.ConnectionStrings["ApplicationDefault"].ConnectionString;
private readonly static string m_providerName = ConfigurationManager.ConnectionStrings["ApplicationDefault"].ProviderName;
readonly variables are allowed to be initialized only in class declaration/contructor and are better optimized for performance than regular private variables.
And back on the question - it really doesn't matter where you'll initialize these.
Drop the fields and go for automatic properties & make your setters private.
public string ConnectionString {get; private set;}
public string ProviderName {get; private set;}
Rob

How to use a a string of one class in another class?

I have a class in test.cs in which I have a string value string user="testuser". I want to use the test.cs's user value in another class. How can I do this?
Declare the string public:
public string user = "testuser";
Then you can access it from another class via
Test.user
However, depending on what exactly you want, you should perhaps make the field read-only:
public readonly string user = "testuser";
Or use a property, bound to a backing field:
public string User
{
get { return this.user; }
}
In fact, properties are the canonical way of making information accessible from the outside except for very few, very special cases. Public fields are generally not recommended.
As Ant mentioned in a comment, there is also the option of making it a constant (assuming it is, in fact, a constant value):
public const string user = "testuser";
Make a public property.
Public string TestUser
{
get { return testUser;}
}
You should make a property of user and expose this to any other class that want to read or write it's value.
class MyClass
{
private static string user;
public static string User
{
get { return user; }
set { user = value; }
}
}
class MyOtherClass
{
public string GetUserFromMyClass()
{
return MyClass.User;
}
}
public class AClass
{
// declarations
private string _user = "testUser";
// properties
public string User { get { return this._user;} set { this._user = value; } }
}
then call your class property, e.g.
AClass myClass = new AClass();
string sYak = myClass.User;
As suggested in the earlier answers, making "user" into a Property is the ideal technique of accomplishing this. However, if you want to expose it directly anyhow, you should use static to avoid having to instantiate an object of that class. In addition, if you don't want the demo class to manipulate the value of user, you should declare is readonly as well, like below
public static readonly user="text user";

Categories

Resources