Reputation: 427
I have a generic class that I use to define a range of values. I would like to have a method only for int type which returns a random value in this range. How can I have a method for a specific type in a generic class ? Is it possible at all ? Here is my class :
public class Range<T> where T : IComparable<T>
{
public T Minimum { get; set; }
public T Maximum { get; set; }
public Range(T Minimum, T Maximum)
{
this.Minimum = Minimum;
this.Maximum = Maximum;
if (!IsValid())
{
this.Minimum = Maximum;
this.Maximum = Minimum;
}
}
public bool IsValid()
{
return this.Minimum.CompareTo(this.Maximum) <= 0;
}
}
Upvotes: 0
Views: 362
Reputation: 249556
You can use the way static fields work in generics to specify a custom delegate that will serve as the implementation for the method:
public class Range<T> where T : IComparable<T>
{
public T Minimum { get; set; }
public T Maximum { get; set; }
// GetRandomNumber specific implementation, the field can have a different value for a specific `T`
public static Func<Range<T>, T> GetRandomNumberHelper = (self) => throw new NotImplementedException("Not implemented for type " + typeof(T).FullName);
public T GetRandomNumber()
{
return GetRandomNumberHelper(this);
}
}
public class Program
{
public static void Main()
{
// Assign the delegate in a static constructor or a main
Range<int>.GetRandomNumberHelper = self => new Random().Next(self.Minimum, self.Maximum);
}
}
Another option would be to used a derive type for a certain T
, as suggested in another answer here. The problem is that there is no way to prevent at compile time someone from creating a new Range<int>()
instead of new IntRange()
, this may be a problem or not depending on your use case.
A third option would be to use an extension method if you don't need to access the method for a random T
:
public static class RangeExt
{
public static int GetRandomNumberHelper(this Range<int> self)
{
return new Random().Next(self.Minimum, self.Maximum);
}
}
The problem here is that a function that takes a parameter of type Range<T>
will not be able to access the method, only on parameters of type Range<int>
will this method appear. This may be a problem depending on your use case
Upvotes: 0
Reputation: 34152
You could do as Yair Halberstadt says or if you insist on having the function in your class you can do it like this:
public class Range<T> where T : IComparable<T>
{
public T Minimum { get; set; }
public T Maximum { get; set; }
public Range(T Minimum, T Maximum)
{
this.Minimum = Minimum;
this.Maximum = Maximum;
if (!IsValid())
{
this.Minimum = Maximum;
this.Maximum = Minimum;
}
}
public int GetRandomNumber()
{
if (typeof(T) == typeof(int))
{
return new Random().Next(Convert.ToInt32(Minimum), Convert.ToInt32(Maximum));
}
else
throw new Exception("Given type is not integer.");
}
public bool IsValid()
{
return this.Minimum.CompareTo(this.Maximum) <= 0;
}
}
Here is the DEMO
Upvotes: 1
Reputation: 6821
just inherit from Range<int>
public class IntRange : Range<int>
{
public IntRange(int Minimum, int Maximum) : base(Minimum, Maximum)
{
}
public void MySpecificToIntMethod()
{}
}
Upvotes: 2