I want to have a large number of class instances return the same similar fields of data, like in this example implementation:
foreach (SomeClass sc in SomeClasses)
{
System.Console.WriteLine(sc.GetData("1st field"));
System.Console.WriteLine(sc.GetData("Another field"));
System.Console.WriteLine(sc.GetData("and another"));
}
// ---- inside SomeClass:
Dictionary<string, string> myData;
public string GetData(string field)
{
return myData[field];
}
What I don't like is the string hashing, lookup and matching that has to happen over and over again in the example (I assume thats how Dictionary works). I would really like to find a better approach.
Coming from the C world, I thought of assigning all fields a unique integer key, such that I can change into an array lookup:
// ---- inside SomeClass:
string[] MyData;
public string GetData(int field_key)
{
return MyData[field_key];
}
Now the field lookup is efficient, but it just doesn't feel right in these "arrays are evil" times, and it is tedious and error prone to deal with the field_key integer.
I don't know if I'm chasing performance ghosts here, its just that I want to find a design that is both efficient and clean.
Suggestions?
Why don't you want a dictionary look-up? A very efficient implementation of a dictionary would be an index look up of the hash in an array. So the underlying implementation could boil down to the code in your second example. This would make it O(1)
Use the Dictionary
Because the fields are not known at compile time, but rather dynamic and user configurable, I'm going to modify your example program slightly to use an array of properties. Then I'd advocate an approach similar to yours but using your own custom class (here, called MyProperty) rather than string. Performance will be at least as good as (and maybe a tad better than) the string approach, but the benefit is that it gives you more flexibility: if you ultimately decide for performance reasons that you need to use an array or List approach, you can easily embed an array index into your MyProperty class. You'd have to change the implementation of GetData but not your calling code.
public static void Test1() {
SomeClass[] SomeClasses; //created somehow
//in real life, this would be determined dynamically
var properties=new[] {SomeClass.FirstField, SomeClass.AnotherField, SomeClass.AndAnother};
foreach(var sc in SomeClasses) {
foreach(var property in properties) {
Console.WriteLine(sc.GetData(property));
}
}
}
public class SomeClass {
public static readonly MyProperty FirstField=new MyProperty();
public static readonly MyProperty AnotherField=new MyProperty();
public static readonly MyProperty AndAnother=new MyProperty();
private readonly Dictionary<MyProperty, string> myData=new Dictionary<MyProperty, string>();
public string GetData(MyProperty property) {
return myData[property];
}
}
//default implementation of Equals and GetHashCode are fine here
public class MyProperty {}
HOWEVER, since your target application is really about collecting a set of dynamic and user configurable property getters, maybe you really want to make some Funcs? Code like the below will be very fast, and it still has the ability you want, namely it allows you to make a little dynamic, user-configurable list of property getters.
public static void Test2() {
SomeClass[] SomeClasses; //created somehow
//in real life, this would be determined dynamically
var getters=new[] {SomeClass.FirstField, SomeClass.AnotherField, SomeClass.AndAnother};
foreach(var sc in SomeClasses) {
foreach(var getter in getters) {
System.Console.WriteLine(getter(sc));
}
}
}
public class SomeClass {
public static readonly Func<SomeClass, string> FirstField=sc => sc.field0;
public static readonly Func<SomeClass, string> AnotherField=sc => sc.field1;
public static readonly Func<SomeClass, string> AndAnother=sc => sc.field2;
private string field0;
private string field1;
private string field2;
}
If your instances have the same fields, why not just use properties?
foreach (SomeClass sc in SomeClasses)
{
System.Console.WriteLine(sc.FirstField);
System.Console.WriteLine(sc.AnotherField);
System.Console.WriteLine(sc.AndAnother);
}
First, if you're not sure this actually is a performance problem for you, then yes, you are chasing performance ghosts and your current implementation is fine.
But if you found out during profiling that you really need to make this code faster, then your seems fine. “Arrays are evil” is mostly true only in public interfaces, it's fine to use them for implementation.
One thing I would change about your code though: create an enum containing the fields and use that instead of int. It's just as fast and much more readable. If the fields are not known at compile time, using int is fine. If you do know some of the fields at compile time, you could use static properties for them.
Related
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
}
}
I understand that reading from the WebConfigurationManager is slow, so I want to minimize my use of it.
Say I have the following readonly property in my code:
public string SiteLogo {
get {
return WebConfigurationManager.AppSettings["SITE_LOGO"];
}
}
In C# 6.0, I can shorten this so that the "getter" has the default value:
public string SiteLogo { get; } = WebConfigurationManager.AppSettings["SITE_LOGO"];
This, it looks like, would be called every time the class is instantiated, whether that Property is ever used or not.
It looks like the most efficient call is still to declare a Private variable to use in the Property:
public string SiteLogo
{
get
{
if (String.IsNullOrEmpty(_siteLogo))
{
_siteLogo = WebConfigurationManager.AppSettings["SITE_LOGO"];
}
return _siteLogo;
}
}
private string _siteLogo;
This still requires me to create Private variables for all of my getters, which seems overly tedious.
I have discarded the idea of using a Session variable, because reading that and casting it to a String seems like it would still incur more overhead.
I would like to see is a way to Auto Assign the Private Property if it is needed.
If the compiler called each Property's Private field #this, I could use something along these lines:
public string SiteLgo
{
get
{
if (String.IsNullOrEmpty(#this))
{
#this = WebConfigurationManager.AppSettings["SITE_LOGO"];
}
return #this;
}
}
Even better, I should not ever need to explicitly tell the code block to return the Private Property, since that is the getter's job:
public string SiteLogo
{
get
{
if (String.IsNullOrEmpty(#this))
{
#this = WebConfigurationManager.AppSettings["SITE_LOGO"];
}
}
}
If a technique to do that currently exists, I don't know the name of what to call it to look it up.
Have I missed the better way to do what I am after (accessing the Private value without having to create it)?
You missed some class that was introduced in .NET 4.0: Lazy<T>:
private readonly string _siteLogo = new Lazy<string>(() => WebConfigurationManager.AppSettings["SITE_LOGO"]);
// Lazy<T>.Value will call the factory delegate you gave
// as Lazy<T> constructor argument
public string SiteLogo => _siteLogo.Value;
BTW, I wouldn't use lazy-loading for this case... at the end of the day, application settings are already loaded into memory and you aren't accessing from the file.
In fact, AppSettings is a NameValueCollection and it uses hash codes to store keys (taken from MSDN):
The hash code provider dispenses hash codes for keys in the
NameValueCollection. The default hash code provider is the
CaseInsensitiveHashCodeProvider.
In other words, accessing AppSettings has a time complexity O(1) (constant).
I would use lazy-loading if you would need to parse settings some way to avoid re-parsing them everytime.
in my C# class, I want to refer to type of the class itself, is it possible?
my sample code:
in the line of
private static List<CRcpParmPropEle<CParam1, string>> ParmPropList;
I don't want to use "CParam1", I wish to use some general way (like "this") to refer to itself. because I have many classes like CParam1, everyone would need to refer to itself this way.
class CParam1
{
private double m_Prop1;
private static List<CRcpParmPropEle<CParam1, string>> ParmPropList;
public CParam1()
{
}
////-> I wish to replace Cparam1 to something like this
public static List<CRcpParmPropEle<CParam1, string>> getParmPropList()
{
if (ParmPropList == null)
{
ParmPropList.Add(new CRcpParmPropEle<CParam1, string>("Prop1", "BA", 0, false));
//-> I wish to replace Cparam1 to something like this
}
return ParmPropList;
}
public string Prop1
{
get
{
return m_Prop1.ToString();
}
set
{
m_Prop1 = -1;
double dW1;
if (double.TryParse(value, out dW1))
{
m_Prop1 = dW1;
}
}
}
public class CRcpParmPropEle<T,TProp>
{
public Func<T, TProp> getter;
public Action<T, TProp> setter;
public string PropName { get; set; }
public string ColPos { get; set; }
public int ColNum { get; set; }
public int RowNum { get; set; }
public bool ReadOnly { get; set; }
public CRcpParmPropEle(string strPropName, string strColPos, int nRowNum, bool bReadOnly)
{
PropName = strPropName;
ColPos = strColPos;
RowNum = nRowNum;
ReadOnly = bReadOnly;
var prop = typeof(T).GetProperty(PropName); //typeof(rcpObj).GetProperty(propName);
getter = (Func<T,TProp>)Delegate.CreateDelegate(typeof(Func<T,TProp>), prop.GetGetMethod());
setter = (Action<T,TProp>)Delegate.CreateDelegate(typeof(Action<T,TProp>), prop.GetSetMethod());
}
}
In general, no. There is no way to do this. Since in the contexts where this would typically be used, one is writing code specific to the type anyway, and since we are used to having to specify the type name for static members anyway, this doesn't seem like much of a hardship.
But, there are a couple of alternatives that could work in your scenario, both involving generics.
The first is to delegate the construction of the new object to a generic helper method:
public static List<CRcpParmPropEle<CParam1, string>> getParmPropList()
{
if (ParmPropList == null)
{
AddToList(ParmPropList, "Prop1", "BA", 0, false);
}
return ParmPropList;
}
private static void AddToList<T>(List<CRcpParmPropEle<T, string>> list, string s1, string s2, int i, bool f)
{
list.Add(new CRcpParmPropEle<T, string>(s1, s2, i, f));
}
In this way, the actual type is inferred from the type of the List<T> object being passed in, and so doesn't need to be restated. Of course, you don't get out of specifying the type somewhere. It just doesn't wind up at this particular call site.
Another option is to use a static helper class to implement the static functionality of your CParam1 class:
static class ParmPropClass<T>
{
private static List<CRcpParmPropEle<T, string>> ParmPropList;
public static List<CRcpParmPropEle<T, string>> getParmPropList()
{
if (ParmPropList == null)
{
ParmPropList.Add(new CRcpParmPropEle<T, string>("Prop1", "BA", 0, false));
}
return ParmPropList;
}
}
Then when you use the static members, you have to specify the type name as ParmPropClass<CParam1> (or whatever, depending on what you wind up naming the helper class). Again, you don't get out of specifying the type name somewhere, but the call site doesn't need to.
In fact, if you are doing this kind of pattern exactly in a number of locations, the generic helper type might be a better way to go, since then you don't have to copy/paste code all the time (a recipe for failing to fix some bug in all the places it was copied to).
There is no straight forward or easy to implement answer here. I'll give you three options but I don't think any of these would be easier than just changing all of the classes. If I had to do this right I would use a dependency injector. in the long run you will be better off and you'll be able to handle this stuff easier next time around. If I had to do it fast and desperate I would use reflection.
Option 1 - Reflection
You could assemble the List at runtime using reflection.
Look at this post for an example of creating a list at runtime with reflection.
Generic list by using reflection
This will make your code really nasty to maintain and you will have to use reflection throughout to manage the list. You would probably add more headaches in runtime errors and difficulty debugging than just changing it everywhere
Option 2 - Common Base Class
If you can make all the CPARAM1 type objects implement from a common base class CPARAMBASE you could define the list using the common base class.
private static List<CRcpParmPropEle<CParamBase, string>> ParmPropList;
Option 3 - Dependency Injection
This isn't something you can just cover in a SO answer but look at dependency injection.
You create an interface between all of the CPARAM type classes and then you inject a concrete type for based on what type it is being injected into.
[Inject]
private static List<CRcpParmPropEle<ICParam, string>> ParmPropList;
In your dependency Injection you could define that ICParam instance would be.
this.Bind<List<CRcpParmPropEle<ICParam, string>>>()
.To<List<CRcpParmPropEle<CParam1, string>>>()
.WhenInjectedInto(typeof(CParam1));
Look up Ninject and then Contextual Binding and http://www.ninject.org/wiki.html
My example:
class MyClass
{
public int a = 1;
public static List<MyClass> list = new List<MyClass>();
}
class Program
{
static void Main(string[] args)
{
MyClass.list.Add(new MyClass() { a = 5 });
MyClass.list.Add(new MyClass() { a = 10 });
foreach (MyClass item in MyClass.list) Console.WriteLine(item.a);
Console.ReadKey();
}
This code works, and shows that my list, which is statically defined within the MyClass class itself, is populating as I'd expect.
Is there any reason not to define my list in this manner?
Such a solution is used sometime, f.e. to implement the Singleton or Register-Resolve patterns.
But you should keep in mind that it's not well suited for multithread environment. Typically, a static collection should be private, and access methods (including property getter and setter) should be synchronized.
In additional, static fields/properties are difficult to an unit testing.
Actually this code shows a lot of sign of (very) bad desing.
First of all one better doesn't make fields public. All other classes/object can now alter the value of that variable in objects. Perhaps you don't see much problems with that, but imagine that at one point in time you want to restrict the range of values that variable can have, or that it depends on the value of another field. Properties (with getters and setters) and methods are used to shield an field from external usage, they need to guarantee that the object always remains in a valid state.
Next about the list, again don't make such lists public - unless you are confident that there is no problem -. But furthermore using statics is by some researchers considered to be bad design as well. The list maintains a state, but since it is static, this is a global state. Global states are problematic since they don't allow (easy) unit testing, and can become problematic if for some reason the list should be not that global.
In case you really want to make some access point for data, you can perhaps consider making a class that stores such list and pass it around in your program.
There are a few exceptions, for instance the Flyweight pattern where one indeed maintains a global state. Those examples are merely used to increase performance. For instance:
public class FlyWeightInstance {
private int value; //<- private field
private static Dictionary<int,FlyWeightInstance> dic = new Dictionary<int,FlyWeightInstance>(); //<- private static cache
private int FlyWeightInstance (int value) { // <-- private constructor
this.value = value;
}
public static FlyWeightInstance (int value) {
FlyWeightInstance res;
if(!dic.TryGetValue(value,out res)) {
res = new FlyWeightInstance(value);
dic.Add(value,res);
}
return res;
}
}
I have a static string class for my database so that I always spell the tables and columns they way they were designed.
I've currently got about 500 lines of code in this one class, but here is a short example:
public const string PURCHASING = "PURCHASING";
public const string SCHED_PURCH = "SCHED/PURCH";
public const string SCHEDULING = "SCHEDULING";
To create a readonly static string array of the "Clerk" department, I use this static declaration:
public static string[] CLERK_DEPT {
get {
return new string[] { PURCHASING, SCHEDULING, SCHED_PURCH };
}
}
There are many lines of code like this in my database strings class.
Today, I happened across this active post where someone was doing something very similar:
How do I prevent the modification of a private field in a class?
The answer there provided a way to provide a readonly string array that I had not considered before:
You must return a copy of your array.
public String[] getArr() {
return arr == null ? null : Arrays.copyOf(arr, arr.length);
}
That has me wondering now if someone out here knows of a more efficient way of passing back my readonly string array.
I must admit that I've always abhorred the idea of the return new string[] in my code.
So, is there? ...a more efficient and cleaner way of doing this or have I already created the best solution?
There's no such thing as an immutable array, basically.
If you trust all your callers, you could tell them not to mutate the array. An alternative is to provide a read-only wrapper:
private static readonly ReadOnlyCollection<string> clerkDepartments =
new ReadOnlyCollection<string>(
new[] { "PURCHASING", "SCHED/PURCH", "SCHEDULING" });
public static readonly ReadOnlyCollection<string> ClerkDepartments
{ get { return clerkDepartments; } }
Note that although ReadOnlyCollection<T> isn't a totally immutable collection, only code with access to the underlying collection could change it - and as the only code which "knows" about the array is the initializer which passes it to the constructor, you're basically safe unless someone cracks out reflection :)
Perhaps use a ReadOnlyCollection?
http://msdn.microsoft.com/en-us/library/ms132474.aspx