I created a specialization for a generic like code below:
public class BaseGeneric<T>
{
public static T DoStuff()
=> default;
}
public class SpecializedFromBaseGeneric : BaseGeneric<int>
{
public static new int DoStuff()
=> 789;
}
Now to call the DoStuff() method I would like to use var result = BaseGeneric<int>.DoStuff();
When I run this code, result is 0 instead of 789. The debugger shows that the call will enter the DoStuff() from public class BaseGeneric<T> instead of SpecializedFromBaseGeneric.
What am I doing wrong?
Later edit
I also tried to create specialization in the below format but that does not even compile:
public class BaseGeneric<T> where T : int
{
public static T DoStuff()
=> 789;
}
I want to do several specializations and use the call similar to the one specified above for int data type BaseGeneric<int>.DoStuff(). And for each specialization use the same syntax where only data type is changed but different implementation is used (eg: for string that would be BaseGeneric<string>.DoStuff()). How to achieve this behaviour?
public class BaseGeneric<T> where T : IConvertible
{
public static T DoStuff()
{
if (typeof(T) == typeof(int))
{
return (T)(object)789;
}
if (typeof(T) == typeof(string))
{
return (T)(object)"ss";
}
return default(T);
}
}
However, as the asnwer here suggests, this is brittle, and doesn't cover every possible usage.
var result = BaseGeneric<int>.DoStuff()
This one calls the function of a base class. It returns new T(), that equals new int(), that equals zero.
var result = SpecializedFromBaseGeneric.DoStuff()
This one will return what you need.
Related
We have an abstract class BaseClass (note generic arg!) with a method called me.
Me returns this.
If we use Me in the concrete classes we will get a return type object.
Then we have to cast the result of Me to the type we originally are working with.
How can we achieve that Me returns the actual type of this? In this example type A?
public abstract class BaseClass<TIdentifier>{
public virtual object Me{ get { return this; } }
}
public class A: BaseClass<long>
{
}
public class B: BaseClass<long>
{
}
public class controller{
public void SomeMethod(){
var a = new A();
var b = new B();
var aObject = a.Me; // this will be of type object
var aObjectCasted = (A)aObject; // cast to original
// How I want it
var aConcrete = a.Me; // this returns type a
}
}
Update
Since some people really, desperately (wink:-)) wish to understand what I'm actually trying to do.
With NHibernate we are doing this:
var result = Session.Get<A>(idToLookUp);
In some cases it happens that result isn't of type A but is of type AProxy, due to laze loading etc. Now if we want to cast result to something else: we will get an invalidcastexception because the actual type of result isn't A but AProxy. And that type can't be casted. We can only cast type A to the other type.
A workaround for this is described here: http://sessionfactory.blogspot.be/2010/08/hacking-lazy-loaded-inheritance.html. That's where the Me property in the above examples comes in.
So to get result of type A and not of type AProxy we now have to do this:
var result = (A)Session.Get<A>(idToLookUp).Me;
Note we have to cast me back to type A if we want to get to read and know the property of result.
My question: can we get rid of the casting and adjust the Me property so we instantly return the concrete type?
Hope it's clear now.
You could use an interface on your derived classes:
public interface IStrongTypedMe<T>
{
T Me();
}
Your derived classes would become:
public class A: BaseClass<long>, IStrongTypedMe<A>
{
public new A Me()
{
return base.Me() as A;
}
}
This is assuming you can change A, of course.
Update:
I understand the issue now (only had time to read the linked article now).
Try using an extension method to do the casting for you like this:
public static TReturnType As<TReturnType,TIdentifier>(this BaseClass<TIdentifier> proxyObject)
where TReturnType : class
{
return proxyObject.Me as TReturnType;
}
And you'd use it like:
var result = Session.Get<A>(idToLookUp).As<A,long>();
No changes to A or B required.
You can change the return type of this property to the definition of parent class
public abstract class BaseClass<TIdentifier>
{
public virtual BaseClass<TIdentifier> Me{ get { return this; } }
}
If you want to return exactly the same class you can make some workaround by adding the result type in the generic type parameter
public abstract class BaseClass<TIdentifier, TMe>
where TMe : BaseClass<TIdentifier, TMe>, new()
{
public virtual TMe Me { get { return (TMe)this; } }
}
public class A : BaseClass<long, A>
{
}
Unfortunately, C#, unlike Java, does not support return type covariance. Otherwise you could just override the property Me in the subclasses like this to get what you want:
public abstract class BaseClass<TIdentifier> {
public virtual object Me { get { return this; } }
}
public class A: BaseClass<long>
{
public override A Me { get { return this; } } // wont work in C#
}
public class B: BaseClass<long>
{
public override B Me { get { return this; } } // wont work in C#
}
Mikhail Neofitov provides a good workaround though.
In order to do something like this:
var aObject = A.Me();
Me will need to be a static method.
A static method doesn't have a this.
If your not using a static method, you have the this - otherwise how are you willing to call the class method? You just need to cast it to the correct type.
Update Due To Edit:
You have this code:
var a = new A();
var aObject = a.Me;
Now what are you expecting here?
You have a which is from type A.
By using var you can't have multiple different return types from the Me geter.
The problem seems to be the implicit definition of the variable using var. When you are using var in this case, the compiler cannot determine the correct type for aObject in the editor. So take the following code for example:
public abstract class BaseClass<TIdentifier>
{
public virtual object Me {get {return this;} }
}
public class A : BaseClass<TIdentifier>
{
public int X
{
get {return 1;}
}
}
public class B : BaseClass<TIdentifier>
{
}
public class controller{
public void SomeMethod(){
var a = new A();
var b = new B();
var aObject = a.Me;
var aObjectCasted = (A)aObject;
// the environment cannot determine the correct type for aObject
// without compiling and running. At this time in the editor,
// this will be recognized as a type object. It will not
// understand aObject.X and will not compile
Console.WriteLine(aObject.X);
// During run-time, this will work. aObject will be defined as type A
Console.WriteLine(aObject.GetType().GetProperty("X").GetValue(aObject));
// this will output A for the type
Console.WriteLine(aObject.GetType());
}
}
Without being able to modify A and B, using the GetProperty, GetMethod, etc. methods on the implicitly defined variable seems like it will be your only hope.
Update:
You can reference this to see the types of calls you can make on a Type object. It seems like you will have to do this more dynamically that desired to achieve the functionality you want. The object will not be defined correctly before compiling if trying to do it implicitly.
var aConcrete = a.Me; in your code will indeed return yield a type A for aConcrete at compile time, but not in the editor.
From MSDN: "It is important to understand that the var keyword does not mean "variant" and does not indicate that the variable is loosely typed, or late-bound. It just means that the compiler determines and assigns the most appropriate type."
Consider I have these classes
class BaseClass
{
public int Variable {get; set;}
}
class Class1:BaseClass
{
public Class1()
{
Variable=1;
}
}
class Class2:BaseClass
{
public Class2()
{
Variable=2;
}
}
In another place I want to do this:
public BaseClass MyMethod(int i)
{
//I want if i is 1 this method returns Class1
//And if i is 2 this method returns Class2.
}
A solution is using switch statement. But my namespace has a lot of class and using switch results a lot of code lines.
Your comment "But my namespace has a lot of class and using switch results a lot of code lines." tells me that you are doing something wrong.
This is classic problem, easily solved by factory pattern, using switch would be the best solution here:
switch(num) {
case 1: return new Class1();
case 2: return new Class2();
default: throw new ArgumentException();
}
Maybe you should split your namespace?
Other solution with is a bit ugly because you will lose compile time checking, is to use Activator:
return (BaseClass)Activator.CreateInstance("AssemblyName", "Class" + num)
Based on comment, 100 classes and must select one.
public static class AmazingFactory {
private static IDictionary<int, Type> _num2Type;
private static void InitializeFactory() {
var type = typeof(BaseClass);
// get all subclasses of BaseClass
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
foreach(var type in types) {
int numberAtTheEnd = int.Parse(Regex.Match(type.Name, #"\d+$").Value);
_num2Type[numberAtTheEnd] = type;
}
}
public static BaseClass Create(int num) {
if (_num2Type == null)
InitializeFactory();
return (BaseClass)Activator.CreateInstance(_num2Type[num]);
}
}
Looks like you don't want to return a class, but rather an instance of a class. The next question is where do you want to get your object from? If they are stored in some collection like
items = new List<BaseClass>();
items.add(new Class1());
items.add(new Class2());
then you can write something like
public BaseClass MyMethod(int i)
{
return items.First(item=>item.Variable == i);
}
If you want to create a new instance with each call to MyMethod than you'll have to use switch\if (or use Reflection, but that's not a recommended approach)
I have taken the following class from another SO question:
public class Range<T> where T : IComparable<T>
{
public T Minimum { get; set; }
public T Maximum { get; set; }
public override string ToString() { return String.Format("[{0} - {1}]", Minimum, Maximum); }
public Boolean IsValid() { return Minimum.CompareTo(Maximum) <= 0; }
public Boolean ContainsValue(T value)
{
return (Minimum.CompareTo(value) <= 0) && (value.CompareTo(Maximum) <= 0);
}
}
I would like, however, to create another class that contains many instances of this class, and can execute a foreach loop on them all, returning true if the number passed is contained in any one of the ranges:
public class Ranges<T> where T : Range<T>
{
private List<Range<T>> rangelist;
public void add(Range<T> range)
{
rangelist.Add(range);
}
public Boolean ContainsValue(T value)
{
foreach (Range<T> range in rangelist)
{
if (range.ContainsValue(value)) return true;
}
return false;
}
}
However, i am getting the error The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Range<T>'. There is no implicit reference conversion from 'T' to 'System.IComparable<T>'.
What exactly is going wrong here?
You don't seem to need the constraint where T : Range<T>
Just repeat the comparable constraint:
public class Ranges<T> where T : IComparable<T>
{
}
If you rewrite your second class slightly, you'll see why:
public class Ranges<U> where U : Range<U>
{
private List<Range<U>> rangelist;
public void add(Range<U> range)
{
rangelist.Add(range);
}
...
}
The error is telling you the compiler does not know if U is convertible to IComparable<U>, which is apparent from the declaration of Ranges<U> and Range<T> (Range<T> does not implement any interfaces).
More importantly, you have a recursing generic argument!
If U is Range<U>, then your class looks like Ranges<Range<T>> where T is U, and so on and so forth.
From what I can tell, you're not looking to write:
Ranges<Range<int>> x = ...;
But rather:
Ranges<int> x = ...;
Which would mean:
public class Ranges<T> where T : IComparable<T>
{
private List<Range<T>> rangelist;
...
You don't need new classes for that, use linq.
list1.All(x=>list2.Any(y=>y == x))
UPDATE: You are saying : I would like, however, to create another class that contains many instances of this class, and can execute a foreach loop on them all, returning true if the number passed is contained in any one of the ranges:
So effectively you have list of lists. Or more generally IEnumerable of IEnumerables.
There is enough standard generic data structures to handle this scenario
public static class ListOfListExtention {
public static bool ContainAny( this List<List<int>> lists, int number ) {
return lists.Any(l=>l.Any(x=>x == number))
}
}
Which can be rewritten in more generic way using IComparable interface
public static class ListOfListExtention {
public static bool ContainAny<T>
(this List<List<int>> lists, int value ) where T : IComparable<T> {
return lists.Any(l=>l.Any(x=>x == value))
}
}
So to compare with accepted answer, why wrap List in new class if you can just have one extension method.
I am having some troubles with generics and inheritance. I have an abstract class called CriteriaBase whose job it is to determine if an entity T matches the criteria defined in any sub-classes. The sub-classes have to implement a method which returns a Func representing the criteria. The problem arises when I try to use generics for the Func. Hopefully some code will illustrate my problem.
public abstract class CriteriaBase<T, U>
where T : ICrossoverable
where U : IChromosome
{
protected abstract Func<U, bool> Criteria { get; }
//some code removed for brevity
private int GetNumberOfCriteriaMatches(T season)
{
//1. works
//Func<IChromosome, bool> predicate = c => c.Genes == null;
//return season.Chromosomes.Count(predicate);
//2. doesn't work - The type arguments for method 'int
//System.Linq.Enumerable.Count<TSource>(this IEnumerable<TSource>,
//Func<TSource, bool>)'
//cannot be inferred from the usage. Try specifying the type arguments
//explicitly.
return season.Chromosomes.Count(Criteria);
}
}
My intention is that the CriteriaBase class should be generic and completely reusable.
An example sub-class:
public class TopTeamsPlayingEachOtherCriteria : CriteriaBase<Season, MatchDay>
{
//some code removed for brevity
protected override Func<MatchDay, bool> Criteria
{
get { return matchDay =>
matchDay.Fixtures.Count(
fixture =>
fixture.HomeTeam.TableGrouping.Ordering == 1
&& fixture.AwayTeam.TableGrouping.Ordering == 1) > 1; }
}
}
The problem is in the GetNumberOfCriteriaMatches() method. Option 2 is how I originally wrote the code but I get the compile error as listed. If I use option 1 then the code compiles but it means that when I override Criteria in the sub-class, I have to use IChromosome instead of MatchDay which doesn't work (I need to access specific features of a MatchDay). In my simple mind, options 1 and 2 are equivalent. Option 2 simply replaces IChromosome with a generic type U which is restricted to a class that implements IChromosome.
Is what I'm trying to achieve possible? If so, what am I missing/misunderstanding? If not, how should I approach this problem?
For completeness (included at the end as I'm not sure how much it helps with the question), here are the two entities that I'm currently using for T (Season) and U (MatchDay).
public class Season : ICrossoverable
{
private readonly IEnumerable<MatchDay> _matchDays;
public Season(IEnumerable<MatchDay> matchDays)
{
_matchDays = matchDays;
}
public IEnumerable<MatchDay> MatchDays
{
get { return _matchDays; }
}
//ICrossoverable implementation
public IEnumerable<IChromosome> Chromosomes
{
get { return _matchDays; }
}
}
public class MatchDay : IChromosome
{
private readonly int _week;
private readonly List<Fixture> _fixtures;
public MatchDay(int week, List<Fixture> fixtures)
{
_week = week;
_fixtures = fixtures;
}
//some code removed for brevity
public IEnumerable<Fixture> Fixtures
{
get { return _fixtures; }
}
//IChromosome implementation
public IEnumerable<IGene> Genes
{
get { return Fixtures; }
}
}
Well this is the problem:
public IEnumerable<IChromosome> Chromosomes
You're only declaring that you're returning a sequence of IChromosome values. Your criterion expects MatchDay values. You happen to know that it's actually returning a sequence of MatchDay values, but the compiler doesn't.
You could use Cast<> to check this at execution time:
return season.Chromosomes.Cast<U>().Count(Criteria);
... or you could change Chromosomes to return an IEnumerable<MatchDay>. Unfortunately we can't really tell whether that's a valid answer or not as we don't know how ICrossoverable is declared. Perhaps you should make ICrossoverable generic in the element type?
You should use keyword in before U in CriteriaBase definition. Something like this:
public abstract class CriteriaBase<T, in U>
where T : ICrossoverable
where U : IChromosome
Update. It will not work.
Try to specify type explicitly
private int GetNumberOfCriteriaMatches(T season)
{
....
return season.Chromosomes.Count<IChromosome>(Criteria);
}
I have 2 base classes FirstBase and SecondBase. I also have 2 class derive from them, DerivedFirst and DerivedSecode and both of them has almost of same property. Source code is like below.
public abstract class FirstBase
{
//some method
}
public abstract class SecondBase
{
//some method
}
public class DerivedFirst : FirstBase
{
//override methods of its parent
public static implicit operator DerivedFirst(DerivedSecond second)
{
//doing some logic here
}
}
public class DerivedSecond : SecondBase
{
//override methods of its parent
public static implicit operator DerivedSecond(DerivedFirst first)
{
//doing some logic here
}
}
From this code I can create instance of DerivedFirst and assign to DerivedSecond without any problem. However when I try to convert list of them like code below, It has no result.
List<DerivedFirst> firstList;
List<DerivedSecond> secondList;
//doing some operation here
List<DerivedSecod> test = firstList.Cast<DerivedSecond>(); // don't have any output here.
How can I convert firstList to List()?
User-defined implicit conversions are considered only at compile time, not at run-time (source). You can use Select instead:
List<DerivedSecond> foo = firstList.Select(x => (DerivedSecond)x).ToList();
Your desired behavior does not work. The static implicit operator is nothing more than a fancy way to write code. DerivedFirst cannot really be casted into a DerivedSecond.
The call of FirstList.Cast<DerivedSecond> works since LINQ streams over the input list while accessing its items. As soon as you access any item in the resulting IEnumerable<DerivedSecond> you get an InvalidCastException.
Try this Visual Studio Test code to see what I mean:
[TestClass]
public class UnitTest1 {
class DerivedA {
public static implicit operator DerivedA(DerivedB b) {
return new DerivedA();
}
}
class DerivedB {
public static implicit operator DerivedB(DerivedA a) {
return new DerivedB();
}
}
[TestMethod]
public void TestMethod1() {
IList<DerivedA> lista = new List<DerivedA> {
new DerivedA()
};
var casted = lista.Cast<DerivedB>();
try {
DerivedB b = casted.First();
Assert.Fail();
} catch (InvalidCastException) {
// exception will be thrown
}
}
}
Edit:
The only solution to "cast" the objects is to use the "Select" method:
var casted = lista.Select(a => (DerivedB)a);
You have just talked about Variance. C# actually introduces Co-variance in .NET 4.0. So if you are in C# 4.0, you can easily do this using out operator in your list.
Check my article
http://www.abhisheksur.com/2010/06/c-40-features.html
I hope this would help you.
Otherwise you can use Loop to cast each individual objects to create a separate list of that type.