Simulate deriving from a value type - c#

I am building a calculator, and I would like to have a type called ButtonDigit, which may contain chars 0 to 9, and I would like to call it ButtonDigit'. Ideally it would be derived fromchar`, but that isn't allowed, and I don't want an object like:
public class ButtonChar
{
public char Value { get; set; }
}
I find that rather clumsy having to always instantiate a ButtonChar object and access the Value property when I want the character stored. What would be ideal is a type of alias for the char set 0-9, but we don't get that. Am I stuck with a ButtonChar object, or a plain char and always checking it's in the range?

Use a generic class to handle different types
public class Button<T>
{
public T {get;set;}
}
You can add a generic validation system on the setter - for example by keeping a list of Func that would be applied to any input, eg:
var validations = new List<Func<T, bool>>();
if (validations.Any(validation => !validation(tValue))) {
throw new InvalidValueException(tValue);
}
// in the char example
validations.Add(myChar => myChar <= '9' && myChar >= '0');

Char is a struct, so you can't inherit it. I would say the custom ButtonChar class is a decent approach though.
Another approach is to just create a bunch of char constants
public static class MyConstants
{
public static char Zero{get{return '0';}}
....
}
The range comparison will be easy since it's a sequential range 0-9

Related

How to have type-safety dependent on a number? (like generics are dependent on a Type)

I want a Type that is "for" a certain number, and another Type for another number. But I don't want to have to manually define a Type for each number like Level1024 and Level1000. I want it to be simple to instantiate an instance of the Level class for each number, like we can do with generics where we can create a Level<string> and a Level<int> without needing to define a separate Level for each of them.
Here's the idea:
Level<1024> topPlayerOf1K;
Level<1000> Abe = new Level<1000>();
topPlayerOf1K = Abe; //This should show a squiggly line in Visual Studio.
How can I achieve that or something like that?
Numbers literals are not considered types in C# like they are in TypeScript, and cannot be used as generic parameters like template parameters in C++.
At the minimum you would have to create types for each of the number literals you want to use. The approach could look like this:
interface IConstantInt { int Value { get; } }
class ConstantInt1000 : IConstantInt { public int Value => 1000; }
class ConstantInt1024 : IConstantInt { public int Value => 1024; }
class Level<TConstantInt> where TConstantInt : IConstantInt { }
var level1000 = new Level<ConstantInt1000>();
var level1024 = new Level<ConstantInt1024>();
It would be good to autogenerate this code if you're going to have many of those. This is not a great solution, but without knowing more about your program and what kind of errors you're trying to prevent, in the abstract, that's a way that you could encode number literals in the type system.
Edit: here's one way that you could access the value inside the class:
class Level<TConstantInt> where TConstantInt : IConstantInt
{
readonly int _intValue;
public Level(TConstantInt constantInt) =>
_intValue = constantInt.Value;
}
class Level
{
// Optional utility factory method, helps with type inference
public static Level<TConstantInt> Create<TConstantInt>(TConstantInt constantInt)
where TConstantInt : IConstantInt =>
new(constantInt);
}
// Now creation looks like this:
var level1000 = Level.Create(new ConstantInt1000());
var level1024 = Level.Create(new ConstantInt1024());

Sort (Array array, System.Collections.IComparer? comparer) - parameter or implementation?

The Methode Array.Sort() has the following signature
public static void Sort (Array array, System.Collections.IComparer? comparer);
It looks like you need to pass an IComparer reference. But what is really needed is that array needs to implements IComparable, isn't it?
I see this syntax the first time. Is this common? How can I differentiate between a real parameter? Is there somewhere more information about this topic (in general)?
Important/Edit: ATM I'm reading a C# book and it says about Sort.Array (translated from German to English):
To the first parameter we pass the array to be sorted, in our case
arr. The second parameter is of type IComparer interface. Of course,
you can't pass an instance of type IComparer to the method call,
because interfaces are not instantiable. This is not how the type
specification of the second parameter should be understood. Instead,
the second parameter simply requires that the fist argument passed to
it be an object that implements the interface IComparer - whether the
object is of type DemoClass, Circle,
Basically he says that the second parameter is kind of a description for the first parameter. Is he correct or maybe that's just wrong and the source for my confusion?
https://openbook.rheinwerk-verlag.de/visual_csharp_2012/1997_04_008.html
I just implemented the following snippet. So this could be a way how to pass the second parameter, right?
Array.Sort(shapes, (a, b) => {
if (a.GetArea() < b.GetArea()) return -1;
else if (a.GetArea() > b.GetArea()) return 1;
return 0;
});
If you do not pass the comparer it will use the default comparer implementation for the Array items. But if you have a special comparer then you can pass your own custom Comparer to sort the elements.
Suppose you have a Class of Students (Array of Students), and your default Student comparer can be based on total marks. However, a maths teacher may want to sort the Students based on marks for the Maths only, in that case maths teacher can write his custom MathsRankComparer and pass it to the Sort method so that he will get the Students ordered by marks in Maths.
Similarly, English or Science teacher can pass the respective comparers to get their required ranking/ordering/sorting.
Hope this helps in understanding use of that overload.
Update: some examples to understand details.
public class Student: IComparable<Student>
{
public int ID { get; set; }
public string Name { get; set; }
public float TotalMarks { get; set; }
public float ScienceMarks { get; set; }
public float MathsMarks { get; set; }
public float EnglishMarks { get; set; }
public int CompareTo(Student other)
{
if (this.TotalMarks == other.TotalMarks)
return 0;
if (this.TotalMarks < other.TotalMarks)
return -1;
return 1;
}
}
public class MathsMarksBasedComparer : System.Collections.Generic.IComparer<Student>
{
public int Compare(Student a, Student b)
{
if (a.MathsMarks == b.MathsMarks)
return 0;
if (a.MathsMarks < b.MathsMarks)
return -1;
return 1;
}
}
public class EnglishMarksBasedComparer : System.Collections.Generic.IComparer<Student>
{
public int Compare(Student a, Student b)
{
if (a.EnglishMarks == b.EnglishMarks)
return 0;
if (a.EnglishMarks < b.EnglishMarks)
return -1;
return 1;
}
}
And finally, you can use them like this.
Student[] arr = new Student[100]; // Ignore this, you can use other styles of declaration
Array.Sort(arr, new EnglishMarksBasedComparer());
Array.Sort(arr, new MathsMarksBasedComparer());
Array.Sort(arr);
Basically he says that the second parameter is kind of a description for the first parameter. Is he correct or maybe that's just wrong and the source for my confusion?
It's not wrong it's just worded a bit confusingly.
The IComparer is a nullable type (defined by the questionmark at the end of IComparer). This states that the IComparer is optional/does not have to be passed. However as Mahesh Bongani already meantioned in his reply - internaly if you do not provide a comparer it takes the defualt comparer of the object.
So for this particular funtion if you would pass a Array with objects that do not implement a comparable the function wouldn't be able to sort the elements properly.
I have seen IComparer a few times and am unsure what implements it as standard - as far as lists, arrays and things go. I do know that numbers implement it and I think string does too.
You can though custom implement this inferface. If memory serves me correctly, it provides just one method (interface so you have to write logic yourself) that returns an int. -1 (<0) is lower ranked, +1(>0) is higher ranked, 0 is the same.

Constrain a string parameter to be a constant from a specific class

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
}
}

How to access properties from an array of class objects in C#?

Character[] PlayerOne = new Character[5];
PlayerOne[1] = new BladeWarrior();
PlayerOne[2] = new FistWarrior();
PlayerOne[3] = new Archer();
PlayerOne[4] = new RedMage();
PlayerOne[5] = new BlueMage();
I know through polymorphism, a BladeWarrior can be a Character but it cant be the other way around. My problem is that when I try to access an element of an array. Player[1] for example, I cant access functions and variables from the BladeWarrior class. It's only letting me access variables and functions from the Character class which the BladeWarrior class inherits from.
I'm going to need to be able to access Bladewarrior functions/variables if Im going to want 2 characters to fight.
I was thinking I could use the "as" function to set PlayerOne[1] as the specific object . Not exactly like this:
string s = objArray[i] as string;
The line of code above is just to get an idea of which "as" Im talking about.
What is a solution to this problem?
I'm going to need to be able to access Bladewarrior functions/variables if Im going to want 2 characters to fight.
It looks like you are attempting to do a multiple dispatch: you want the call of
Fight(PlayerOne[i], PlayerOne[j]);
to call a function that knows the exact types of both characters. There are different tricks that you can use to achieve double dispatch in single dispatch languages, most notably, the visitor pattern. Starting with C#4, you could also use dynamic to implement double dispatch in a relatively clean and easy to read way:
static class FightArena {
public static void Fight(dynamic a, dynamic b) {
try {
DoFight(a, b);
} catch {
Console.Error.WriteLine("{0} and {1} cannot fight", a, b);
}
}
private static void DoFight(BladeWarrior a, Archer b) {
}
private static void DoFight(BladeWarrior a, FistWarrior b) {
}
private static void DoFight(BladeWarrior a, RedMage b) {
}
private static void DoFight(BladeWarrior a, BlueMage b) {
}
private static void DoFight(BladeWarrior a, BladeWarrior b) {
}
private static void DoFight(Archer a, Archer b) {
}
... // Enumerate all pairs that can fight
}
Now you can write something like this:
FightArena.Fight(PlayerOne[i], PlayerOne[j]);
and the call will reach the exact pair of types based on dynamic types of PlayerOne[i] and PlayerOne[j].
If you have to cast your Character's back to their concrete types for them to fight you are loosing any benefit you would get from polymorphism. If you need to cast to a Character to a Bladewarrior to fight that means you have to write different logic to each character to be able to fight each other. Then if you later add a new character type you'll have to update all of your fight code to support that type.
What you really want to be able to do is to write a generate fight algorithm that can be used to fight any two Character objects without casting them. You could add properties to the Character base class that would indicate the properties that the character has.
For example you could have add a Attacks property to the Character class which would be a list of the attacks the character has which would have a name of the attack and how much damage it does. Then each derived character class would populate its list of Attacks and your fight algorithm would process these attacks. In this way each character could have its own list of attacks, but would not have to be cast to a specific character type to access it.
The end goal here is for any external code to only know about the Character class and not any of its derived classes. That will make your external code cleaner and give you the ability to add or remove character classes in the future.
It is absolutely normal,if you want access BladeWarrior's properties you must convert your Character to BladeWarrior, and you'r right you can use as keyword for this:
BladeWarrior bw = PlayerOne[1] as BladeWarrior;
You are upcasting the instances thats why you are only able to use parent class behaviours and attributes.
I think you will have to do i individually for all instances.
BladeWarrior player1 = new BladeWarrior();
FistWarrior player2 = new FistWarrior();
Archer player3 = new Archer();
//and so on
As you said you can use "as" to cast. If the instance you are trying to cast cannot be casted to the target class you will get an null.
var currentCharacter = PlayerOne[1] as BladeWarrior;
if(currentCharacter != null)
{
....
}
The challenge here is to get a clean way to know what is the right casting.
May be you could use a structure in the array and use a flag to indicate the underliying class
switch(PlayerOne[1].Type)
{
case PlayerTypes.BladeWarrior:
currentCharacter = PlayerOne[1].Character as BladeWarrior;
}
But in general it seems you are not acomplishing the Liskov Subtitution Principle (The L in SOLID principles). You shouldnt need to access to the implementation details of the specific types of characters, Just override some methods or use a more modular(and complex) design based on the strategy pattern.
or you can use interface
public interface ICharacter {
int myValue { get; set;}
void myMethod();
}
public class BladeWarrior : ICharacter {
private int myPrivateValue;
public int myValue { get { return myPrivateValue; } set { myPrivateValue = value; } }
public void myMethod() {
//Do what you want
}
}
ICharacter[] PlayerOne = new ICharacter[5];
PlayerOne[0] = new BladeWarrior();
then you can access your interface methods
ICharacter[0].myMethod();

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