This question already has answers here:
Why can't I declare C# methods virtual and static?
(16 answers)
Closed 9 years ago.
i have a class with a static field and a static function, e.g. like this
public class A {
protected static string[] _eventField = new[] { "SomeValue" };
public static TOut DoSomethingThatDependsOnEventField(TIn input){
//output depends on input and the static _eventField
}
public class Nested1: A {
protected new static string[] _eventField = new[] { "SomethingDifferent" };
}
public class Nested2 : A {
protected new static string[] _eventField = new[] { "SomethingElse" };
}
}
The output and input types of that static method are of no importance here, the only relevant thing is that the output - despite relying on the input, of course - depends on the content of the static field. The implementation of the method doesn't change at all in the derived classes, and all I want is to change that very static field. But whenever I do a call like
var res1 = A.Nested1.DoSomethingThatDependsOnEventField(...);
or
var res2 = A.Nested2.DoSomethingThatDependsOnEventField(...);
the incorrect static field from the base class A is referenced from within the method.
That is, the intended "hiding" / "redefining" of the static field via protected new static string[] _eventField = ... doesn't work - Why is that so?
You cant have an object associated with Static field/member/function , so static field/member/function cannot come into picture in Inheritance also.
Related
This question already has answers here:
Associating enums with strings in C#
(38 answers)
Can enums contain strings? [duplicate]
(6 answers)
Closed 1 year ago.
I know enums can't be strings
I would like a data structure with the utility of an enum, but one which returns strings instead of integers. To be clear, I want the return type to be the enum-like type, not string. Basically, I want to be able to force a property to be usable as a string but is only allowed to be set to a value in a defined set of strings. Something like
stringenum Unit {
Pixels = "px",
Inches = "in"
}
class Settings {
public Unit Unit { get; set; }
}
var settings = new Settings() { Unit = Unit.Pixels };
...
unitLabel.Text = settings.Unit;
I've seen some solutions that just create a class with properties that return a certain string. However, I need the return type to be limited to a set, not just any string.
EDIT FOR CLARIFICATION
Consider my previous example in addition to this method:
public void WriteUnit(Unit unit)
{
Console.WriteLine(unit);
}
// Calling
WriteUnit(Unit.Pixels); // Prints "px"
WriteUnit("px"); // ARGUMENT EXCEPTION
This method will throw an ArgumentException if you pass it a string. It only accepts the type. This is specifically what I'm looking for.
As mentioned in the comments, you cannot directly map an enum to a string.
That said, there is nothing preventing you from creating a map of enum to string values, that can only be accessed via the enum. If you maintain the mapping, you can guarantee that the value always exist.
public enum Unit
{
Pixels,
Inches
}
public static class UnitMapper
{
private static readonly Dictionary<Unit, string> _map
= new Dictionary<UserQuery.Unit, string>()
{
{ Unit.Pixels, "px" },
{ Unit.Inches, "in" }
}
public static string GetUnit(Unit unit)
{
return _map[unit];
}
}
Based on your additional comments, this can be combined with a custom user-defined implicit operator to give you the type of functionality you are looking for, although you will still have to call the overridden .ToString() to output a string.
public struct UnitWrapper
{
private readonly string _unitString;
private readonly Unit _unit;
public UnitWrapper(Unit unit)
{
_unit = unit;
_unitString = UnitMapper.GetUnit(_unit);
}
public static implicit operator UnitWrapper(Unit unit)
{
return new UnitWrapper(unit);
}
public override string ToString() => _unitString;
}
This can then be used as follows:
public class Settings
{
public UnitWrapper UnitWrapper { get; set; }
}
var settings = new Settings { UnitWrapper = Unit.Pixels };
string px = settings.UnitWrapper.ToString();
This question already has answers here:
Are C# readonly field's allowed to be modify outside of the class?
(3 answers)
Prevent other classes from altering a list in a class
(4 answers)
Closed 1 year ago.
I was checking an online tutorial video and I noticed this code modifying a readonly field without constructor and it was working fine. How & Why it works?
public class Journal
{
private readonly List<string> entries = new List<string>();
private static int count = 0;
public int AddEntry(string text)
{
entries.Add($"{++count}: {text}");
return count; // memento pattern!
}
public void RemoveEntry(int index)
{
entries.RemoveAt(index);
}
public override string ToString()
{
return string.Join(Environment.NewLine, entries);
}
}
public class Demo
{
static void Main(string[] args)
{
var j = new Journal();
j.AddEntry("I cried today.");
j.AddEntry("I ate a mango.");
WriteLine(j);
}
}
output:
I cried today.
I ate a mango.
What is really happening here is that a method called on the entries readonly field and it Does NOT change the reference of the entries field.
Changing the reference of the readonly field is a compile error, but calling a method on the readonly (whatever it does internally) has no problem at all
Try the following statement
entries = new List<string>();
and you will see the error
This question already has answers here:
Convert List<DerivedClass> to List<BaseClass>
(13 answers)
Closed 5 years ago.
I have classes which implement interfaces of classes derived from a common base. Is there any way that I can combine these to work with them as a set?
I have been exploring co and contravariance but without success.
Thanks for your help.
void Main()
{
var textAnswers = new IAnswerValidator<TextQuestion, TextAnswer>[] { new NoDogsValidator(), new MaxLengthValidator() };
var dateAnswers = new IAnswerValidator<DateQuestion, DateAnswer>[] { new NotChristmasDayValidator() };
// Can I combine into a list or enumerable?
// var allValidators = new List<IAnswerValidator<QuestionBase, AnswerBase>>();
// allValidators.AddRange(textAnswers);
// allValidators.AddRange(dateAnswers);
// The goal is to be able to combine so as to be able to work on them as a set.
}
public class ValidationResult { }
public class AnswerBase { }
public class TextAnswer : AnswerBase { }
public class DateAnswer : AnswerBase { }
public class QuestionBase { }
public class TextQuestion : QuestionBase { }
public class DateQuestion : QuestionBase { }
public interface IAnswerValidator<TQuestion, TAnswer> where TQuestion : QuestionBase, new() where TAnswer : AnswerBase, new()
{
ValidationResult Validate(TQuestion question, TAnswer answer);
}
public class NoDogsValidator : IAnswerValidator<TextQuestion, TextAnswer>
{
public ValidationResult Validate(TextQuestion question, TextAnswer answer) { return new ValidationResult(); } // simplified
}
public class MaxLengthValidator : IAnswerValidator<TextQuestion, TextAnswer>
{
public ValidationResult Validate(TextQuestion question, TextAnswer answer) { return new ValidationResult(); } // simplified
}
public class NotChristmasDayValidator : IAnswerValidator<DateQuestion, DateAnswer>
{
public ValidationResult Validate(DateQuestion question, DateAnswer answer) { return new ValidationResult(); } // simplified
}
Is there any way that I can combine these to work with them as a set?
Not and keep type-safety.
For example, consider your proposed code:
var allValidators = new List<IAnswerValidator<QuestionBase, AnswerBase>>();
allValidators.AddRange(textAnswers);
allValidators.AddRange(dateAnswers);
Suppose the compiler let you do that. Then what do you say should happen if you do something like this:
QuestionBase question = new TextQuestion();
AnswerBase answer = new TextAnswer();
foreach (var validator in allValidators)
{
validator.Validate(question, answer);
}
In particular, when it gets to the NotChristmasDayValidator element in the list, what's that object going to do when you pass its Validate() method objects that are not DateQuestion and DateAnswer, respectively?
Your goal is fundamentally broken. You say you want to combine all the objects into a single list, but you haven't explained why that's useful nor what you think you'd be able to do with such a list. There are of course ways you can put all those objects into the same list, but only by discarding the type safety. For example, just make your allValidators object a List<object> instead. Then you can put whatever you want in the list. But you'll have to do extra type-checking later, when using the list.
Until if and when you're able to explain a design goal that is safe and sensible, all we can say for now is "no, you can't do that, it's not safe".
I have created for myself several classes of the same structure - "rich enums". So it immediately suggests that it could be somehow simplified by another class I would inherit.
I wrote an example class to show you what such an enum contains:
class RichEnum
{
// ???
}
class MyEnum : RichEnum
{
// FIELDS AND CONSTRUCTOR(S)
public readonly string A;
public readonly int B;
public readonly Object C;
public MyEnum(string A, int B, Object C)
{
this.A = A;
this.B = B;
this.C = C;
}
// STATIC INSTANCES
public static readonly MyEnum Example1 = new MyEnum("string1", 1, "object1");
public static readonly MyEnum Example2 = new MyEnum("string2", 2, "object2");
public static readonly MyEnum Example3 = new MyEnum("string3", 3, "object3");
// SPECIAL INSTANCE
public static readonly MyEnum Default = new MyEnum("default", 0, "default");
// SPECIAL OBJECT FOR ITERATING OVER STATIC INSTANCES
public static readonly MyEnum[] Values = { Example1, Example2, Example3 };
// METHODS
public int GetSomeNumber()
{
return B + 10;
}
}
I have lots of various "MyEnums", but these classes all have the same structure. So they have:
Some public readonly fields (variable number) of various types
One or more constructors
Public static readonly instances
A special field used to return the value if none of those instances can match a condition. For example when I use MyEnum.Values.FirstOrDefault(...), that would return default when nothing is found
Some methods
Is there a way to create one class of this structure and then just inherit from it, making the process more simplified and less error-prone?
It seems you're reinventing the wheel: Headspring.Enumeration.
So, if your goal is just to have such a "rich" enumeration class available to you, there's a Nuget package for that; if your goal is to write your own ... well, it never hurts to look at prior art for inspiration.
If you really look at it, these classes have actually nothing in common that could be abstracted:
They have a different amount of static and non-static fields
The types of the fields are different
The values of each field differ
The names of the fields differ
The methods differ
Unless you find something they have in common, you can't create a base class. What could help you would be a code snippet that contains the general layout of such a class to speed up your typing.
Take a look at this code I posted on CodeProject a LONG time ago.
http://www.codeproject.com/Articles/13293/Descriptive-Enumerations
I won't post all the code, although it's not too bad, but here's an example of actually using it. In this case, I am trying to define an enum of a passenger's airline seat preference.
public class SeatType : DescriptiveEnum<SeatType, int>
{
public static readonly SeatType Window = new SeatType("Window Seat", 1);
public static readonly SeatType Aisle = new SeatType("Aisle Seat", 2);
public static readonly SeatType AnythingExceptSeatNearBathroom = new SeatType("Anything Except Seat Near Bathroom", 3);
private SeatType(string desc, int code)
: base(desc, code)
{
}
}
So, as you can see, that's pretty clean. Of course, you could certainly extend this to add additional methods, or include a "default", etc.
Then you can use it like this:
class Example
{
public static void Main(string[] args)
{
SeatType c = SeatType.AnythingExceptSeatNearBathroom;
Console.WriteLine(c.Description);
Console.WriteLine(SeatType.AnythingExceptSeatNearBathroom == c);
foreach (SeatType seat in SeatType.GetEnumMembers())
{
Console.WriteLine(String.Format("Seat type code: {0} - description: {1}",seat.Code,seat.Description));
}
Console.ReadLine();
}
}
The base DescriptiveEnum class also has conversion operators baked in, so it works JUST like enums do. That is, you can say:
SeatType c = (SeatType) SomeMethodThatReturnsAnInt();
This question already has answers here:
When do you use the "this" keyword? [closed]
(31 answers)
Closed 9 years ago.
Say I have a simple sample console program like below. My question is in regards to this. Is the sole use of this just so you can use the input variable name to assign to the instance variable? I was wondering what the use of this is other than used in the context of this program?
public class SimpleClass {
int numberOfStudents;
public SimpleClass(){
numberOfStudents = 0;
}
public void setStudent(int numberOfStudents){
this.numberOfStudents = numberOfStudents;
}
public void printStudents(){
System.out.println(numberOfStudents);
}
public static void main(String[] args) {
SimpleClass newRandom = new SimpleClass();
newRandom.setStudent(5);
newRandom.printStudents();
}
}
Previously, when I needed to assign a value to an instance variable name that shares similarities to the input value, I had to get creative with my naming scheme (or lack of). For example, the setStudent() method would look like this:
public void setStudent(int numberOfStudentsI){
numberOfStudents = numberOfStudentsI;
}
From that example above, it seems like using this replaces having to do that. Is that its intended use, or am I missing something?
Things are quite the opposite of how you perceive them at the moment: this is such an important and frequently used item in Java/C# that there are many special syntactical rules on where it is allowed to be assumed. These rules result in you actually seeing this written out quite rarely.
However, except for your example, there are many other cases where an explicit this cannot be avoided (Java):
referring to the enclosing instance from an inner class;
explicitly parameterizing a call to a generic method;
passing this as an argument to other methods;
returning this from a method (a regular occurrence with the Builder pattern);
assigning this to a variable;
... and more.
this is also used if you want to a reference to the object itself:
someMethod(this);
There is no alternative to this syntax (pun intended).
It's also used to call co-constructors, and for C# extension methods.
'this' simply refers to the object itself.
When the compilers looks for the value of 'numberOfStudents', it matches the 'closest' variable with this name. In this case the argument of the function.
But if you want to assign it to the class variable, you need to use the 'this.'-notation!
In the method
public void setStudent(int numberOfStudents){
this.numberOfStudents = numberOfStudents;
}
for example.
'this.numberOfStudents' references the class variable with the name 'numberOfStudents'
'numberOfStudents' references the argument of the method
So, this method simple assigns the value of the parameter to the class variable (with the same name).
in c# you use this to refer the current instance of the class object immagine you have class like this from msdn
class Employee
{
private string name;
private string alias;
private decimal salary = 3000.00m;
// Constructor:
public Employee(string name, string alias)
{
// Use this to qualify the fields, name and alias:
this.name = name;
this.alias = alias;
}
// Printing method:
public void printEmployee()
{
Console.WriteLine("Name: {0}\nAlias: {1}", name, alias);
// Passing the object to the CalcTax method by using this:
Console.WriteLine("Taxes: {0:C}", Tax.CalcTax(this));
}
public decimal Salary
{
get { return salary; }
}
}
class Tax
{
public static decimal CalcTax(Employee E)
{
return 0.08m * E.Salary;
}
}
class MainClass
{
static void Main()
{
// Create objects:
Employee E1 = new Employee("Mingda Pan", "mpan");
// Display results:
E1.printEmployee();
}
}
/*
Output:
Name: Mingda Pan
Alias: mpan
Taxes: $240.00
*/
You have different scopes of variables in Java/C#. Take this example below. Although this.numberOfStudents and numberOfStudents have the same name they are not identical.
public void setStudent(int numberOfStudents){
this.numberOfStudents = numberOfStudents;
}
this.numberOfStudents is a variable called numberOfStudents that is in the instance of this class. this always points on the current instance.
public void setStudent(int numberOfStudents) that numberOfStudents is a new variable that is just available in this method.
keyword "this" refers to an object of the current class (SimpleClass) on the fly.
public class SimpleClass(){
private int a;
private int b;
private int c;
public SimpleClass(int a, int b){
this.a = a;
this.b = b;
}
public SimpleClass(int a, int b, int c){
// this constrcutor
this(a,b);
this.c = c;
}
}