I am wondering is it possible to 'spread' tuple's values in a way to properly match method arguments.
For example:
public (int, object) GetTuple() {
return (5, null);
}
public void ReceiveMultipleArguments(int a, object b) { ... }
The call of ReceiveMultipleArguments method like this:
ReceiveMultipleArguments(GetTuple());
will result in this error:
CS7036: There is no argument given that corresponds to the required formal parameter 'b' of 'Method1(int, object)'
The possible solution is to destructure tuple manually then provide each value as method argument, but is there a way to do it shorter, like spread operator that exists in javascript, for example?
C# is a strongly typed language, so you cannot pass tuple (which has its own class ValueTuple class).
So, you could just define overload for the method:
public void Test()
{
ReceiveMultipleArguments(GetTuple());
}
public (int, object) GetTuple()
{
return (5, null);
}
public void ReceiveMultipleArguments((int a, object b) #params) => ReceiveMultipleArguments(#params.a, #params.b);
public void ReceiveMultipleArguments(int a, object b) { ... }
You could change the signature of the method to support params of object elements. Then you could unpack the tuple into individual elements and use that as parameter.
public void Main()
{
var tuple = GetTuple();
var items = UnpackTuple(tuple).ToArray();
DoSomethingWith(items);
}
public void DoSomethingWith(params object[] data)
{
foreach (var d in data)
{
Console.WriteLine(d);
}
}
public IEnumerable<object> UnpackTuple(ITuple tuple)
{
for (var index = 0; index < tuple.Length; index++)
{
yield return tuple[index];
}
}
public ITuple GetTuple()
{
return Tuple.Create(5, "second", 2.489, 'G');
}
However, I would strongly advice you to move away from tuples if you need to move them around in your program. From experience, I have seen that this will lead to a messy code base that is hard to understand and change.
Instead, define classes for your tuples. Lets say you need to pass an object, let's say an apple, and a count for how many apples into some method. The class could be a generic class such as:
public class CountOf<T>
{
public CountOf(T value, int count)
{
this.Value = value;
this.Count = count;
}
public T Value { get; }
public int Count { get; set; }
}
Or non-generic, such as:
public class CountedObject
{
public CountedObject(object obj, int count)
{
this.Object = obj;
this.Count = count;
}
public object Object { get; }
public int Count { get; set; }
}
Use case:
public void Main()
{
var apple = new Apple();
var countedApples = new CountOf<Apple>(apple, 10);
DoSomethingWith(countedApples);
var countedObject = new CountedObject(apple, 10);
DoSomethingWith(countedObject);
}
public void DoSomethingWith(CountOf<Apple> countedApples)
{
// do something here
}
public void DoSomethingWith(CountedObject countedObject)
{
// do something here
}
public class Apple { }
public class CountOf<T>
{
public CountOf(T value, int count)
{
this.Value = value;
this.Count = count;
}
public T Value { get; }
public int Count { get; set; }
}
public class CountedObject
{
public CountedObject(object obj, int count)
{
this.Object = obj;
this.Count = count;
}
public object Object { get; }
public int Count { get; set; }
}
maybe this help you:
static void Main(string[] args)
{
ReceiveMultipleArguments(GetTuple());
Console.WriteLine();
}
public static (int, object) GetTuple()
{
return (5, null);
}
public static void ReceiveMultipleArguments((int, object) p)
{
Console.WriteLine(p.Item1);
Console.WriteLine(p.Item2);
}
Related
I want to create a class with a property that "variably" points to some other property in another class.
Imagine a class (called "Limiter") with several integer properties (Limit1, Limit2, etc).
I now want a second class ("LimitWatcher") which can "watch" one of those limits. But I want to be able to set which particular limit it is watching in the constructor. I eventually want several instances of LimitWatcher, each one pointing to a separate Limit. The Limit values themselves may change after the Watchers have been instantiated, but the watcher must always see the current value of the Limit that it is watching. So basically, I want to store a reference to an integer.
I know I can accomplish this using reflection (see example below), but I feel as though there might be a simpler way.
using System;
namespace ConsoleApplication4
{
public class Limiter
{
public int limit1 { get; set; } = 10;
public int limit2 { get; set; } = 20;
public void Update()
{
limit1++;
limit2++;
}
}
public class LimitWatcher
{
public LimitWatcher(Limiter lim, string propName)
{
myLimiter = lim;
limitName = propName;
}
private Limiter myLimiter { get; }
public string limitName { get; set; }
//can I do this without reflection:
public int FooLimit { get { return (int)typeof(Limiter).GetProperty(limitName).GetValue(myLimiter); } }
}
class Program
{
static void Main(string[] args)
{
Limiter lim = new ConsoleApplication4.Limiter();
LimitWatcher w1 = new LimitWatcher(lim, nameof(lim.limit1));
LimitWatcher w2 = new LimitWatcher(lim, nameof(lim.limit2));
lim.Update();
Console.WriteLine($"1st watcher sees {w1.FooLimit}"); //11
Console.WriteLine($"2nd watcher sees {w2.FooLimit}"); //21
Console.ReadKey();
}
}
}
You could use a Func int the constructor, something like:
private Limiter limiter;
private Func<Limiter, int> propertyAccesor;
public LimitWatcher(Limiter lim, string propName, Func<Limiter, int> propertyAccesor)
{
this.propertyAccesor = propertyAccesor;
}
public bool LimitExceeded()
{
int propertyValue = propertyAccesor(limiter);
return propertyValue > 20;
}
You could use dynamic expressions:
using System.Linq.Expressions;
public class LimitWatcher
{
public LimitWatcher(Limiter lim, string propName)
{
myLimiter = lim;
limitName = propName;
var parameter = Expression.Parameter(typeof(Limiter), "x");
var member = Expression.Property(parameter, propName);
var finalExpression = Expression.Lambda<Func<Limiter, int>>(member, parameter);
getter = finalExpression.Compile();
}
private Func<Limiter, int> getter;
private Limiter myLimiter { get; }
public string limitName { get; set; }
public int FooLimit { get { return getter(myLimiter); } }
}
Inspired by this article
I have a function as below:
public var UpdateMapFetcher(int stationID, int typeID)
I need this function to return either string or int.
My return value is set as below
if (finaloutput == "System.String")
{
// param1[i] = Convert.ChangeType(typeID_New.ToString(), typeof(string));
returnvalue = returnvalue.ToString();
return returnvalue;
}
else if (finaloutput == "System.Int32")
{
int a=0;
a = Convert.ToInt32(returnvalue);
return a;
}
How to have either one data type as return value in dynamic environment.
My intuition tells me, that you are trying to convert string value to some type. In that case you can use:
public T UpdateMapFetcher<T>(int stationID)
{
//var someValue = "23";
return (T)Convert.ChangeType(someValue, typeof(T));
}
//then
var typed = UpdateMapFetcher<int>(6);
In case you don't know T, you can use mapping (0-int, 1-string, etc.):
public object UpdateMapFetcher(int stationID, int type)
{
var typeMap = new []{ typeof(int), typeof(string)};
//var someValue = "23";
return Convert.ChangeType(someValue, typeMap[type]);
}
//then
var untyped = UpdateMapFetcher(6, 0/*0 is int*/);
if (untyped.GetType() == typeof(int))
{ /*is int*/
}
Another solution is to use implicit conversions:
public class StringOrInt
{
private object value;
public ValueType Type { get; set; }
public static implicit operator StringOrInt(string value)
{
return new StringOrInt()
{
value = value,
Type = ValueType.String
};
}
public static implicit operator StringOrInt(int value)
{
return new StringOrInt()
{
value = value,
Type = ValueType.Int
};
}
public static implicit operator int(StringOrInt obj)
{
return (int)obj.value;
}
public static implicit operator string(StringOrInt obj)
{
return (string)obj.value;
}
}
public enum ValueType
{
String,
Int
}
And then (simplified):
public static StringOrInt UpdateMapFetcher(int stationID, int typeID)
{
if (typeID == 0)
return "Text";
return 23;
}
private static void Main(string[] args)
{
var result = UpdateMapFetcher(1, 1);
if (result.Type == ValueType.String) { }//can check before
int integer = result;//compiles, valid
string text = result;//compiles, fail at runtime, invalid cast
}
you can return an object. You'd have to subsequently check for types in your consuming method. I assume that won't be a problem in your usecase.
your method signature is therefore:
public object UpdateMapFetcher(int stationID, int typeID)
You also have the option of using the out keyword, which permits you to accept both into variables and check after the function has been called.
public void UpdateMapFetcher(int stationID, int typeID, out int intValue, out string strValue)
// or int return val and out string value
public int UpdateMapFetcher(int stationID, int typeID, out string strValue)
With the use appearing something like this:
int intVal;
string strVal;
UpdateMapFetcher(stationID, typeID, out intVal, out strVal);
if (strVal != null)
{
doSomethingWithString(strVal);
}
else
{
doSomethingWithInt(intVal);
}
Frankly, I would just return a Tuple, with string being non-null indicating string value to use, and null as indicator for int return
public Tuple<string, int> UpdateMapFetcher(int stationID, int typeID) {
if (finaloutput == "System.String")
{
// param1[i] = Convert.ChangeType(typeID_New.ToString(), typeof(string));
returnvalue = returnvalue.ToString();
return new Tuple<string, int>(returnvalue, 0);
}
else if (finaloutput == "System.Int32")
{
int a=0;
a = Convert.ToInt32(returnvalue);
return new Tuple<string, int>(null, a);
}
}
On consumer side
var rc = UpdateMapFetcher( .... );
if (rc.Item1 != null) {
// code to use string value
} else {
// code to use int value
}
I would choose to return an object of new class which might look like this:
class Result {
public string StringValue { get; }
public string Int32Value { get; }
public bool IsString { get; }
public bool IsInt32 { get; }
public Result(string value) {
StringValue = value;
IsString = true;
}
public Result(int value) {
Int32Value = value;
IsInt32 = true;
}
}
This way you can check which Type is it by using Isxxx property. You can also enhance this with validation in value geters. F. e., for string it might look like this:
public string StringValue {
get {
if (IsString)
return m_stringValue;
throw new InvalidOperationException("Value is not a string.");
}
}
You can't really do exactly that, but there are several ways to do more or less what you want. You'd probably be better off change the design a little though.
Two ideas:
Either change your code to use two different methods, and call each of them as needed instead.
..Or return an object, which you can cast however you like..
..Or, use a generic method with TypeDescriptor, like the following.
Note that we here convert the value to string first even if it was an int, since we can then use a common method ConvertFromString() to convert it to whatever type T was.
public T UpdateMapFetcher<T>(int stationID, int typeID) {
// To allow parsing to the generic type T:
var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));
if(converter != null)
{
return (T)converter.ConvertFromString(returnvalue.ToString());
}
else
{
return default(T);
}
}
Usage:
var result = MyExtensions.UpdateMapFetcher<string>(1, 2);
or:
var result = MyExtensions.UpdateMapFetcher<int>(1, 2);
You can return Object and cast to type which you want.
public Object UpdateMapFetcher(int stationID, int typeID)
if (finaloutput == "System.String")
{
// param1[i] = Convert.ChangeType(typeID_New.ToString(), typeof(string));
returnvalue = returnvalue.ToString();
return returnvalue;
}
else if (finaloutput == "System.Int32")
{
int a=0;
a = Convert.ToInt32(returnvalue);
return a;
}
A type that can contain either one type or another is usually called (unsurprisingly) Either. It is a special case of a sum type, basically a discriminated union, tagged union, or disjoint union with exactly two cases (instead of an arbitrary number).
Unfortunately, there does not exist an implementation of an Either type in the standard libraries, but there are plenty of implementations to be found on Google, GitHub, and elsewhere … and porting one of the existing implementations from e.g. Haskell or Scala isn't that hard, either.
It looks a bit like this (forgive my code, I don't actually know C♯ that well):
using System;
abstract class Either<A, B>
{
public abstract bool IsLeft { get; }
public abstract bool IsRight { get; }
public abstract A Left { get; }
public abstract B Right { get; }
public abstract A LeftOrDefault { get; }
public abstract B RightOrDefault { get; }
public abstract void ForEach(Action<A> action);
public abstract void ForEach(Action<B> action);
public abstract void ForEach(Action<A> leftAction, Action<B> rightAction);
private sealed class L : Either<A, B>
{
private A Value { get; }
public override bool IsLeft => true;
public override bool IsRight => false;
public override A Left => Value;
public override B Right { get { throw new InvalidOperationException(); } }
public override A LeftOrDefault => Value;
public override B RightOrDefault => default(B);
public override void ForEach(Action<A> action) => action(Value);
public override void ForEach(Action<B> action) {}
public override void ForEach(Action<A> leftAction, Action<B> rightAction) => leftAction(Value);
internal L(A value) { Value = value; }
}
private sealed class R : Either<A, B>
{
private B Value { get; }
public override bool IsLeft => false;
public override bool IsRight => true;
public override A Left { get { throw new InvalidOperationException(); } }
public override B Right => Value;
public override A LeftOrDefault => default(A);
public override B RightOrDefault => Value;
public override void ForEach(Action<A> action) {}
public override void ForEach(Action<B> action) => action(Value);
public override void ForEach(Action<A> leftAction, Action<B> rightAction) => rightAction(Value);
internal R(B value) { Value = value; }
}
public static Either<A, B> MakeLeft(A value) => new L(value);
public static Either<A, B> MakeRight(B value) => new R(value);
}
And you'd use it like this:
static class Program
{
public static void Main()
{
var input = Console.ReadLine();
int intResult;
var result = int.TryParse(input, out intResult) ? Either<int, string>.MakeLeft(intResult) : Either<int, string>.MakeRight(input);
result.ForEach(r => Console.WriteLine("You passed me the integer one less than " + ++r), r => Console.WriteLine(r));
}
}
I need to design a data structure that holds different types of values (doubles, strings, datetimes, etc.). The list of types is dynamically created by user. Based on that list another list of values should be created.
Then this "record" of values is to be sent by WCF and stored in dynamically created db table. I'm starting with desiging this solution in c#. My current status is shown below. I'm not satisfied with my present solution, especially with factory and enums. Is there better way to do the things right?
Enum for my types:
public enum ValueType { Decimal, String, Boolean };
then interface:
public interface IValueType
{
object Data { get; }
string ToString();
ValueType? Type { get; }
}
base class:
public abstract class ValueType<T> : IValueType
{
protected T _Value;
public ValueType(T value)
{
_Value = value;
}
public object Data
{
get { return _Value; }
}
public ValueType? Type
{
get { return null; }
}
public T Value { get; private set; }
public override string ToString()
{
return _Value.ToString();
}
}
one of implementation:
public class DecimalValueType : ValueType<decimal>
{
public DecimalValueType( decimal val ) : base(val)
{}
public DecimalValueType(double val) : base((decimal)val)
{}
public DecimalValueType(int val) : base((decimal)val)
{}
}
then factory:
public static class ValueTypeFactory
{
private static Dictionary<ValueType, Type> dictValueType = new Dictionary<ValueType, Type>()
{
{ ValueType.Decimal, typeof(DecimalValueType) },
{ ValueType.String, typeof(StringValueType) },
{ ValueType.Boolean, typeof(BooleansValueType) }
};
private static Dictionary<Type, Type> dictSimple = new Dictionary<Type, Type>()
{
{ typeof(decimal), typeof(DecimalValueType) },
{ typeof(double), typeof(DecimalValueType) },
{ typeof(int), typeof(DecimalValueType) },
{ typeof(string), typeof(StringValueType) },
{ typeof(bool), typeof(BooleansValueType) }
};
public static IValueType MakeByValueType(ValueType type, params object[] initValues)
{
IValueType retObject = null;
if (dictValueType.ContainsKey(type) )
{
Type t = dictValueType[type];
retObject = (IValueType)Activator.CreateInstance(t,initValues);
}
return retObject;
}
public static IValueType MakeByType(params object[] initValues)
{
IValueType retObject = null;
if ( initValues.Length > 0 )
{
Type type = initValues[0].GetType();
if (dictSimple.ContainsKey(type))
{
Type t = dictSimple[type];
retObject = (IValueType)Activator.CreateInstance(t, initValues);
}
}
return retObject;
}
}
sample use:
List<IValueType> lista = new List<IValueType>();
lista.Add(new DecimalValueType(12));
lista.Add(new StringValueType("Test"));
lista.Add(new BooleansValueType(true));
lista.Add(ValueTypeFactory.MakeByValueType(ValueType.Decimal, 10.1));
lista.Add(ValueTypeFactory.MakeByType(5.12));
lista.Add(ValueTypeFactory.MakeByType("Test2"));
I would be happy with any advice.
Here is a simpler solution that covers the usages in your post and avoids the ValueType subclass noise:
public abstract class ValueType
{
public enum Types { Decimal, String, Boolean };
public abstract object Data { get; }
public abstract Types Type { get; }
private ValueType() {}
protected class TypedValueType<T> : ValueType
{
private Types type;
public TypedValueType(T value, Types type) : base()
{
this.Value = value;
this.type = type;
}
public override object Data { get { return this.Value; } }
public override Types Type { get { return this.type; } }
public T Value { get; private set; }
public override string ToString()
{
return this.Value.ToString();
}
}
public static implicit operator ValueType(decimal value) { return new TypedValueType<decimal>(value, Types.Decimal); }
public static implicit operator ValueType(double value) { return new TypedValueType<decimal>((decimal)value, Types.Decimal); }
public static implicit operator ValueType(int value) { return new TypedValueType<decimal>((decimal)value, Types.Decimal); }
public static implicit operator ValueType(string value) { return new TypedValueType<string>(value, Types.String); }
public static implicit operator ValueType(bool value) { return new TypedValueType<bool>(value, Types.Boolean); }
}
Sample usage:
public class Demo
{
public static void Main()
{
List<ValueType> lista = new List<ValueType>();
lista.Add(1);
lista.Add("Test");
lista.Add(true);
lista.Add(10.1);
lista.Add(5.12);
lista.Add("Test2");
foreach(var value in lista) Console.WriteLine(value.Data + " - " + value.Type.ToString());
Console.ReadKey();
}
}
Since it appears that you are wanting to restrict the types of values that can be contained, the nested TypedValueType class is marked protected and the ValueType constructor is marked private. Implicit operators are used to provide the "factory" logic for producing the appropriate typed TypeValueType subclasses for the values that are to be casted.
Here is the output from executing this as a console app:
1 - Decimal
Test - String
True - Boolean
10.1 - Decimal
5.12 - Decimal
Test2 - String
This question already has answers here:
Getting hash of a list of strings regardless of order
(5 answers)
Closed 8 years ago.
Let's say I have a class
public class MyClass
{
public string Type { get; set; }
public int Id { get; set; }
}
and I have a collection class that is simply a strongly typed List
public class MyClassList : List<MyClass>
{
public MyClassList(IEnumerable<MyClass> enumerable) : base (enumerable) {}
}
I want MyClassList to be able to generate a unique hash-code for MyClassList based on the contents. The hash-code of MyClass should be based on both properties. The hash-code of MyClassList should be the same even if the order of the objects is different.
To handle the ordering issue I was thinking I could order the list before generating the hash-code, but I'm not sure how to generate the hash-code of the list.
For optimal performance I would try to avoid iterating the whole collection every time GetHashCode is called. The purpose of GetHashCode is to improve performance to a point better than evaluating every element. So I might try maintaining the hash code when elements in the list are changed like this.
class Program
{
static void Main(string[] args)
{
MyClassList l = new MyClassList() { new MyClass() {Type="Bob", Id=1}, new MyClass() {Type="Jones", Id=2}};
MyClassList l2 = new MyClassList() { new MyClass() { Type = "Jones", Id = 2 }, new MyClass() { Type = "Bob", Id = 1 } };
MyClassList l3 = new MyClassList() { new MyClass() { Type = "Jones", Id = 2 }};
Console.WriteLine("{0} {1} {2}", l.GetHashCode(), l2.GetHashCode(), l3.GetHashCode());
l3.Add(new MyClass() { Type = "Bob", Id = 1 });
Console.WriteLine("{0}", l3.GetHashCode());
}
}
public class MyClass
{
public string Type { get; set; }
public int Id { get; set; }
public override int GetHashCode()
{
return (Type.GetHashCode() % 0x8000) | (int)((uint)Id.GetHashCode() & 0xFFFF0000);
}
}
public class MyClassList : IList<MyClass>
{
List<MyClass> internalList;
int hashCode = 0;
public MyClassList()
{
internalList = new List<MyClass>();
}
private void IncludeInHash(MyClass item)
{
hashCode ^= item.GetHashCode();
}
private void ExcludeFromHash(MyClass item)
{
IncludeInHash(item);
}
public override int GetHashCode()
{
return hashCode;
}
public int IndexOf(MyClass item)
{
return internalList.IndexOf(item);
}
public void Insert(int index, MyClass item)
{
internalList.Insert(index, item);
// Make sure Insert is successful (doesn't throw an exception) before affecting the hash
IncludeInHash(item);
}
public void RemoveAt(int index)
{
MyClass reduce = internalList[index];
internalList.RemoveAt(index);
// Make sure RemoveAt is successful before affecting the hash
ExcludeFromHash(reduce);
}
public MyClass this[int index]
{
get
{
return internalList[index];
}
set
{
MyClass reduce = internalList[index];
internalList[index] = value;
// Make sure these happen atomically; don't allow exceptions to prevent these from being accurate.
ExcludeFromHash(reduce);
IncludeInHash(value);
}
}
public void Add(MyClass item)
{
internalList.Add(item);
IncludeInHash(item);
}
public void Clear()
{
internalList.Clear();
hashCode = 0;
}
public bool Contains(MyClass item)
{
return internalList.Contains(item);
}
public void CopyTo(MyClass[] array, int arrayIndex)
{
internalList.CopyTo(array, arrayIndex);
}
public int Count
{
get { return internalList.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(MyClass item)
{
if (internalList.Remove(item))
{
ExcludeFromHash(item);
return true;
}
else
return false;
}
public IEnumerator<MyClass> GetEnumerator()
{
return internalList.AsReadOnly().GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
The solution given by clto works. Here is an alternative: sort the list by some total ordering (any ordering will do, as long as it is unambiguous). Then you can calculate the hash code using any normal means. You don't need order-independence. You could even use a cryptographic hash function.
I propose this solution (I didn't implement the Equals method) :
public class MyClass
{
public string Type { get; set; }
public int Id { get; set; }
public override int GetHashCode()
{
int hash = 17;
hash = hash + 23 * this.Type.GetHashCode();
hash = hash + 23 * this.Id.GetHashCode();
return hash;
}
}
public class MyClassList : List<MyClass>
{
public MyClassList(IEnumerable<MyClass> enumerable) : base(enumerable) { }
public override int GetHashCode()
{
return this.Aggregate(17, (state, current) => state * 23 + current.GetHashCode());
}
}
The way to generate the hashcode is inspired from Microsoft method to compute the hash value for anonymous objects.
If the order isn't important then you should use a collection that inherently is a set, rather than a list.
Also, it's generally best to not inherit from collections; use composition instead.
So for a collection you can use a HashSet, as it will have set semantics.
To have MyClass use both properties as it's identity just override it's equals and get hash code implementations, or create an IComparer<MyClass> if you can't or don't want to do that.
public class MyClass:IEquatable<MyClass>
{
public string Type { get; set; }
public int Id { get; set; }
public override bool Equals(object obj)
{
return Equals(obj as MyClass);
}
public bool Equals(MyClass other)
{
if (other == null)
return false;
return Type == other.Type &&
Id == other.Id;
}
public override int GetHashCode()
{
return Type.GetHashCode() * 79 + Id;
}
}
Then your collection is as simple as:
HashSet<MyClass> set = new HashSet<MyClass>();
And if you want to compare various sets just use:
HashSet<MyClass>.CreateSetComparer();
I want to access to static fields of a type, which is a class, introduced in a generic function. But compiler always gives me this error
'T' is a 'type parameter', which is
not valid in the given context
here is the code.
public class A
{
public static int Num = 1;
public int GetClassNum<T>() where T : A
{
//return T.Num;
//return default(T).Num;
//return what???
}
}
public class B : A
{
public static int Num = 2;
}
public class C : A
{
public static int Num = 3;
}
I suspect that this has something to do with the fact that interfaces are generally used to filter the typename in a generic function. or must it be always? In this case there should not be a static field. Is there any way I can achieve?
try this:
public class A
{
private static int _num = 1;
public virtual int Num { get { return _num; } set { _num = value; } }
public int GetClassNum<T>(T input) where T : A
{
return input.Num;
}
}
Then override Num in the derived classes
What you are doing is wrong, you are trying to access a type, not an instance.
So how to resolve this,
public class A
{
public static int Num = 1;
public int GetClassNum<T>(T inn) where T : A
{
inn.Num //really
}
}
wait, wait... You cant do this too. Because Num is static and what we have passed (T inn) is a object reference(Only a class can access static fields, not objects).Then how can we make this work. One way is to make T as a static type, so
public static class A
{
public static int Num = 1;
public int GetClassNum<T>(T inn) where T : A // Error here
{
inn. /// no Num
}
}
wait, you cant do this too. Because you cannot use static instances as generic constraint because static is sealed itself.
So How to access Num, change Num to object instance or refer Preets answer for other option.
Static fields belong to type, not instance of the type. You cannot refer to the static elements of the type parameter because they are not inherited.
Make Num not static property:
public class A
{
public virtual int Num
{
get { return 1; }
}
public int GetClassNum<T>(T instance) where T : A
{
return instance.Num;
}
}
public class B : A
{
public override int Num
{
get { return 2; }
}
}
public class C : A
{
public override int Num
{
get { return 3; }
}
}