C# generic defs class - c#

I want to find elegant solution for defs class in C# Example:
Instead of:
class Class1
{
public static readonly string length = "length_Class1";
public static readonly string height = "height_Class1";
public static readonly string width = "width_Class1";
}
class Class2
{
public static readonly string length = "length_Class2";
public static readonly string height = "height_Class2";
public static readonly string width = "width_Class2";
}
Create template class. I thought of the following solution but it looks not so elegant:
internal abstract class AClass
{
}
internal class Class1 : AClass
{
}
internal class Class2 : AClass
{
}
class Class1<T> where T : AClass
{
public static readonly string length = "length_" + typeof(T).Name;
public static readonly string height = "height_" + typeof(T).Name;
public static readonly string width = "width_" + typeof(T).Name;
}
EDIT:
I have a lot of parameter names that I get/set from external data source, I would like to have two Instances of Defs for that. Length , Weight, Height are only for Illustration, there are a lot more.
EDIT:
I chose Generics because I think that there is a way to make the concatination in compile time (like in c++). Is it possible to do that?
Could you help me with more elegant solution?
Thanks!!!

It seems to me that you don't actually need the properties to be static, or the class to be generic. So, you can do something like:
class ParameterNames
{
public string Length { get; private set; }
public string Height { get; private set; }
public string Width { get; private set; }
public ParameterNames(string className)
{
Length = "length_" + className;
Height = "height_" + className;
Width = "width_" + className;
}
}
Although you might want to refactor your code, so that the code that accesses the external resource doesn't need to deal with those parameter names at all:
abstract class ExternalResource
{
private readonly string m_className;
protected ExternalResource(string classname)
{
m_className = className;
}
protected object GetParameterValue(string name)
{
string fullName = name + '_' + m_className;
// actually access the resource using fullName
}
}
public class SpecificParameters : ExternalResource
{
public SpecificParameters(string className)
: base(className)
{ }
public int Length { get { return (int)GetParameterValue("length"); } }
…
}
Doing this wouldn't avoid concatenating strings repeatedly, but I'm not sure why you want to avoid that, doing that should be pretty fast.

Related

Winforms combobox displaying class names instead of actual object name

I have this class that contains a static list
public class TypeList
{
public string Name;
public string NameTag;
public TypeList(string Name, string NameTag)
{
this.Name = Name;
this.NameTag = NameTag;
}
public static List<TypeList> DataType = new List<TypeList>() {
new TypeList("DataType","-1"),
new TypeList("OpOne","1"),
new TypeList("OpTwo","2"),
};
}
I then put the static list called DataType into a combobox:
public void RefreshList()
{
List<TypeList> data = new List<TypeList>();
data = TypeList.DataType;
typeCB.DataSource = data;
typeCB.DisplayMember = "Name";
typeCB.ValueMember = "NameTag";
typeCB.SelectedValue = -1;
typeCB.SelectedText = "Select DataType";
}
However, when I run it, all I get are the classnames in my combobox. Is something wrong with my code? I tried to do
data.Select(x=>x.Name).ToList()
But that just gives me the name portion.
I might be wrong, but based on the Documentation and Example it might be that this Feature only works with public property getters, not public fields:
Gets or sets the property to display for this ListControl.
public class USState
{
private string myShortName;
private string myLongName;
public USState(string strLongName, string strShortName)
{
this.myShortName = strShortName;
this.myLongName = strLongName;
}
public string ShortName
{
get
{
return myShortName;
}
}
public string LongName
{
get
{
return myLongName;
}
}
}
Of course I would also advise against making the list a part of the Type class. A simple Programm scope static would be better. If that is the case and as autoproties have have become a thing by now, this should be enough of a fix:
public class Type
{
public string Name { private set; get } ;
public string NameTag {private set; get };
public TypeList(string Name, string NameTag)
{
this.Name = Name;
this.NameTag = NameTag;
}
}
//use in the class of main, the form or some similar central point
static List<Type> TypeList = new List<Type>();

How to define baseclass or interface for constants?

In my application, I need to define a same set of Constant values for multiple classes and I want to use one baseclass/interface of all them as type param to my generic class.
//I know following code will not work, just trying to demonstrate the problem
public interface IConstantsDefined
{
static const string DbName;
static const string TableName;
static const string ColumnName;
}
public static class Product : IConstantsDefined
{
public static const string DbName = "ProductDB";
public static const string TableName = "Products";
public static const string ColumnName = "ProductId";
}
public static class Sales: IConstantsDefined
{
public static const string DbName = "SalesDb";
public static const string TableName = "Sales";
public static const string ColumnName = "SaleId";
}
public class DbConnection<TConsts> where TConsts : IConstantsDefined
{
// use TConsts.DbName, TConsts.TableName here
}
I understand that what I wrote above will throw many errors in C#. I know that static class can not inherit from interface. Question I have is, what is the best design/approach to build such a system, keeping performance and memory in mind?
Constants are defined and initialized once.
public interface IConstantsDefined
{
static const string Foo = "Foo";
static const string Bar = "Bar";
}
What you want are abstract get-only fields:
public interface IConstantsDefined
{
string DbName { get };
string TableName { get };
string ColumnName { get };
}
public class Product : IConstantsDefined
{
public string DbName { get { return "ProductDB" } };
public string TableName { get { return "Products" } };
public string ColumnName { get { return "ProductId" } };
}
public class Sales: IConstantsDefined
{
public string DbName { get { return "ProductDB" } };
public string TableName { get { return "Sales" } };
public string ColumnName { get { return "SaleId" } };
}
Since you don't need/want multiple instances of the Product and Sales types you might want to consider dropping the types altogether as this is pretty much the definition of a class:
public class ConstantsDefined
{
public string DbName { get; private set; };
public string TableName { get; private set; };
public string ColumnName { get; private set; };
public static readonly ConstantsDefined Product = new ConstantsDefined()
{
DbName = "ProductDB",
TableName = "Products",
ColumnName = "ProductId",
};
}
You can try as in the comment from #nabuchodonossor. Or, you can create Metadata classes, ProductMetadata and SalesMetadata which implement interface IMetadata. Then when needed, you could use a factory to get metadata instance by passing in the actual Model information(typeof(Sales) for example).
The closest one to achieve wanted is this, using base abstract class:
abstract class Base
{
public abstract string DbName { get; }
}
class Product : Base
{
public override string DbName => "ProductDB";
}
class Sales : Base
{
public override string DbName => "SalesDB";
}
class DbConnection<T> where T : Base
{
public string Test(T instance) => instance.DbName;
}
This indeed require instance, which can be hold by DbConnection, resolved by service provider, etc.
All my Product or Sales class would have is various constants, so I do not want to create instance of these
This requirement basically change everything. It seems you understand constant in given context as "a value which can't be changed". Which is immutable type. Then you do not need generics to construct type with constants, simply pass parameters (as you would do with any immutable type):
class DbConnection
{
public string DbName { get; }
public DbConnection(string dbName)
{
DbName = dbName;
}
}
Usage: instead of mysterious new DbConnection<Product>() you simply do new DbConnection("ProductDB"). If you have multiple parameters, then consider to wrap those and pass instance to constructor. And this is where you end up with abstract class and non-static inheritance as in my first snippet: new DbConnection(new Product()) (while DbConnection will require Base type to pass).

inheriting a class with parameteraized constractor to reuse base properties

i'm trying to minimize use of constractors in derived classes, and have a base class to hold common properties
so i tried as follows
public class sharedData
{
public string GlobMeta;
public int GlobValue;
public sharedData(string meta, int value)
{
GlobMeta = meta;
GlobValue= value;
}
}
public class derivedData: sharedData
{
public string test;
test = string.Format("Shared meta = {0}, Shared Value = {1}",GlobMeta, GlobValue);
}
then use
var shared = new sharedData("desc", 1);
var derived = new derivedData();
var testData = derived.test;
so when i will create instance of derived it will use base (shared) values
wich is common to all derived classes.
how can i implement this, as my idea was to use less memory with large collections of data. and also clean code and ease of use.
You have declared a based class, sharedData, without parameterless constructor. Therefore, any class that inherit that class must define a base constructor. You can't rely on the the compiler do job the job for you anymore.
public class derivedData : sharedData
{
public string test;
public derivedData(string meta, int value) : base(meta, value)
{
// you can't do assignment in the class scope, unless it can be done statically, it has to be inside a method block
test = string.Format("Shared meta = {0}, Shared Value = {1}", GlobMeta, GlobValue);
}
// or, if you prefer to have a parameterless ctor
public derivedData() : base("a default value for meta", default(int))
{
test = string.Format("Shared meta = {0}, Shared Value = {1}", GlobMeta, GlobValue);
}
}
EDIT: It seems that you are using this for global settings, in that case, you need to mark GlobMeta and GlobValue as static. Otherwise they won't be "shared" at all between different instance of sharedData/derivedData.
You should consider rewriting it as this :
public static class SharedData
{
public static string Meta { get; private set; }
public static int Value { get; private set; }
public static void SetData(string meta, int value)
{
Meta = meta;
Value = value;
}
}
public class DerivedData
{
public string Test
{
get { return string.Format("Shared meta = {0}, Shared Value = {1}", SharedData.Meta, SharedData.Value); }
}
}
EDIT 2 : If you need to have various instances of these, use the following :
public class SharedData
{
public string Meta { get; set; }
public int Value { get; set; }
public SharedData(string meta, int value)
{
Meta = meta;
Value = value;
}
}
public class DerivedData : SharedData
{
public string Test
{
get { return string.Format("Shared meta = {0}, Shared Value = {1}", Meta, Value); }
}
public DerivedData(string meta, int value) : base(meta, value)
{
}
// note: this is a copy ctor, changing data after this has been created, will not affect this.
public DerivedData(SharedData data) : base(data.Meta, data.Value)
{
}
}
I was thinking along the same lines as Xiaoy312, and wrote this while he was posting his second example:
public class SharedData
{
internal static string GlobMeta;
internal static int GlobValue;
public SharedData(string meta, int value)
{
GlobMeta = meta;
GlobValue = value;
}
public SharedData(){}
}
public class DerivedData: SharedData
{
public DerivedData() : base()
{
Console.WriteLine("Shared meta = {0}, Shared Value = {1}", GlobMeta, GlobValue);
}
}
Declaring the static variables as 'internal means they will only be accessible in the scope of 'SharedData and any classes derived from it.

Access const with generics C#

I have the following base class:
public class Base
{
public string LogicalName { get; set; }
public int NumberOfChars { get; set; }
public Base()
{
}
public Base(string logicalName, int numberOfChars)
{
LogicalName = logicalName;
NumberOfChars = numberOfChars;
}
}
and the following derived classes:
public class Derived1 : Base
{
public const string EntityLogicalName = "Name1";
public const int EntityNumberOfChars = 30;
public Derived1() : base(EntityLogicalName, EntityNumberOfChars)
{
}
}
public class Derived2 : Base
{
public const string EntityLogicalName = "Name2";
public const int EntityNumberOfChars = 50;
public Derived2()
: base(EntityLogicalName, EntityNumberOfChars)
{
}
}
and I also have this function that is provided by a service:
public IEnumerable<T> GetEntities<T>(string entityName, int numberOfChars) where T : Base
{
//Some code to get the entities
}
My problem is how can I call this function generically? I want to call it with something that looks like this:
public void TestEntities<T>() where T : Base
{
var entities = GetEntities<T>(T.EntityLogicalName, T.EntityNumberOfChars);
//some other code to test the entities
}
This of course doesn't work because at this point T is not known. How can I accomplish something similar to this? EntityLogicalName and EntityNumberOfChars are characteristics that all Base derived classes have and they never change for each derived class. Can I get them from the Base class without instantiating objects or some other way that I am not seeing?
Replace constants with getter abstract properties
public abstract class Base
{
public abstract string LogicalName { get; }
public abstract int NumberOfChars { get; }
public Base()
{
}
}
public class Derived1 : Base
{
public string LogicalName { get { return "Name1"; } }
public int NumberOfChars { get { return 30; } }
public Derived1() : base()
{
}
}
Also, you will be able to put some logic into overriden getter, e.g. :
...
public string LogicalName { get { return this.EntityMap.Name; } }
...
UPDATE: The fact that you do not want to instantiate object from class but want to be able to get that string in a strongly typed manner can be handled in one more way. It is totally separate from answer above ( Since you can't override static props in c#). Consider the following code. We are adding one more class here, but LocatorInner can be a member of BaseClass. We are using this approach a lot in several existing apps.:
public class Locator
{
public static class LocatorInner<T> where T : BaseClass
{
public static string Name { get; set; }
}
public static string GetName<T>() where T : BaseClass
{
return LocatorInner<T>.Name;
}
public static void SetName<T>(string name) where T : BaseClass
{
LocatorInner<T>.Name = name;
}
}
public class BaseClass
{
}
public class DerivedClass: BaseClass
{
static DerivedClass()
{
Locator.LocatorInner<DerivedClass>.Name = "me";
}
}
public class TestClass<T> where T : BaseClass
{
public void Method()
{
var name = Locator.GetName<T>();
}
}
IMHO, I believe using constants here is a bad design decision.
You can either solve the issue using #vittore approach, but for me it sounds like you should use meta-programming with attributes if you're looking to get data from the T generic argument
For example, what about:
public class LogicalNameAttribute : Attribute
{
public LogicalNameAttribute(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public class NumberOfCharsAttribute : Attribute
{
public NumberOfCharsAttribute (int number)
{
Number = number;
}
public string Number { get; private set; }
}
[LogicalName("Name1"), NumberOfChars(30)]
public class Derived1 : Base
{
public Derived1() : base()
{
}
}
Now your service method can extract attribute metadata as follows:
public void TestEntities<T>() where T : Base
{
LogicalNameAttribute logicalNameAttr = typeof(T).GetCustomAttribute<LogicalNameAttribute>();
NumberOfCharsAttribute numberOfCharsAttr = typeof(T).GetCustomAttribute<NumberOfCharsAttribute >();
Contract.Assert(logicalNameAttr != null);
Contract.Assert(numberOfCharsAttr != null);
string logicalName = logicalNameAttr.Name;
int numberOfChars = numberOfCharsAttr.Number;
// Other stuff
}
There's a performance penalty because you need to use reflection to get attributes applied to T, but you gain the flexibility of not forcing derived classes to provide this static info.
As #vittore mentioned, move the properties to base,pass the hard coded values from derived and in creation use just defautl(T)
public IEnumerable<T> GetEntities<T>(string entityName, int numberOfChars) where T : Base
{
yield return default(T); //Is its always class use new constraint and return new T();
}

An object method is required for non static, field method

I've no experience of using C# but as part of one of our college modules we have to create a slot machine application. We created a Gambler class and I have to make a CheckBalance class where I will call the Token method from the Gambler class. But I get the error that is mentioned in the thread title.
Int tokens = Gambler.Tokens;
The above line is where I am getting my error.
This is my code:
enter code herenamespace CasinoClasslibrary
{
public class Gambler
{
public string Name { get; private set; }
public int Age { get; private set; }
public long CreditCardNum { get; private set; }
public int Tokens { get; public set; }
public string Username { get; private set; }
public string Password { private get; public set; }
public Gambler(string Name, int Age, long CreditCardNum, int Tokens, string Username, string Password)
{
this.Name = Name;
this.Age = Age;
this.CreditCardNum = CreditCardNum;
this.Tokens = Tokens;
this.Username = Username;
this.Password = Password;
}
}
public class Cashout : Gambler
{
public Boolean CheckBalance()
{
int tokens = Gambler.Tokens;
return true;
}
}
}
Since you are inheriting from Gambler I suspect that you need to access base.Tokens like:
public Boolean CheckBalance()
{
int tokens = base.Tokens; //here
return true;
}
Otherwise since Toakens is an instance member you have to create object of Gambler and then access it.
There are other errors in your code as well. You haven't defined a default (parameter less) constructor in your base class and you need to call the existing base constructor in your child class.
public class Cashout : Gambler
{
public Cashout()
: base("",0, 0, 1, "", "") //something like this
{
}
public Boolean CheckBalance()
{
int tokens = base.Tokens;
return true;
}
}
Because Cashout inherits from Gambler you can just do this. This is because the Cashout instance will have a Tokens property as well.
public class Cashout : Gambler
{
public Boolean CheckBalance()
{
int tokens = Tokens;
return true;
}
}
However, if you intended the method to be static, you will need an instance of Gambler to access that property and this should be passed into the static method as such.
public class Cashout : Gambler
{
public static Boolean CheckBalance(Gambler myGambler)
{
int tokens = myGambler.Tokens;
return true;
}
}
Finally, if you intended this Tokens property to be static itself, you need to declare it as such
public static int Tokens;
You may also want a static constructor to set it up.
Tokens is not static method but you try to access it through static construct (class level).
can make this work by declaring it static (although that's not likely what you want)
public static int Tokens { get; public set; }
or by instantiating Gambler
new Gambler().Tokens;

Categories