locked
violates the constraint of type parameter 'T' What is it? RRS feed

  • Question

  • Error:
    System.TypeLoadException was unhandled
      Message="GenericArguments[0], "MyCompany.Business.Entity.dll, on MyCompany.Core.Base.BaseData`1[T]' violates the constraint of type parameter 'T'."


    Guys
    Got the above error and I am at loss i have checked and all the classes have a default empty constructor.Google is not much help

    Any suggestions?
    Am I missing something?

    Just in case it helps
    mybase class has a signature like this
     [Serializable()]  
        public abstract class BaseEntity<T> : BaseData<T>, INotifyPropertyChanging, INotifyPropertyChanged   
                                            where T : BaseEntity<T> 
     
      the class I am using looks like   
       public class MyEntity: BaseEntity<MyEntity> 
    {  


    Always happen when a create a new instance of the class

    thanks for any suggestions


    Thanks for your help
    Thursday, March 5, 2009 5:09 PM

Answers

  • It should work.  I'd remove any constraints on T that match the type of the class you're declaring.  So in the following example, you'll want to remove the constraint:

    public class BaseData<T> where T : BaseData<T>
    David Morton - http://blog.davemorton.net/
    • Marked as answer by devBrix Friday, March 6, 2009 1:14 PM
    Thursday, March 5, 2009 6:06 PM

All replies

  • What does BaseData look like?
    David Morton - http://blog.davemorton.net/
    Thursday, March 5, 2009 5:28 PM

  • It  has stuff that wraps Enterprise library validation .Dont want to confuse things though.
    Thanks for your help. This error is really causing lots of trouble as all my entities depends on this data.

     

     [Serializable()]  
        public abstract class BaseData<T> where T : BaseData<T> 
        {  
        }
        
              
     
            
            
              
                
                
                    
                   
                     
                   
     
                  
                
                  
                      
                  

    Thanks for your help
    • Edited by devBrix Thursday, March 5, 2009 6:09 PM
    Thursday, March 5, 2009 5:38 PM
  • I see.

    BaseData<T> has a type constraint on T that T should be of the type BaseData<T>.  In other words, the type that will be represented by T must be of the type or derived from the type BaseData<T>.  My guess is that this is where your original fumble was. 

    The resulting error that happens happens when you inherit from BaseData<T> to create BaseEntity<T>, and you try to add a constraint restricting T to BaseEntity<T>.  Now you're saying that the type put into T at the BaseEntity level has to be restricted to BaseEntity<T>, but you're also saying that the T in BaseEntity<T> is the same type as the T in it's inherited BaseData<T>, but since .NET doesn't allow dual inheritance, no class could possibly inherit from both. 

    Your restrictions won't work to begin with, because you have an infinite recursion in your type parameters, that can't even be solved by doing something like this:

    BaseEntity<BaseEntity<BaseEntity<BaseEntity<BaseEntity<BaseEntity<T>>>>>>

    The reason this won't work is because at some point, you need a class at "T" that isn't a BaseEntity<T>. 

    The only situation I know of where recursive restrictions like this work well is in, say, a dictionary class that's recursive:

    public class RecursiveDictionary : Dictionary<string, RecursiveDictionary>

    {

        public object Value { get; set; }

    }

    This is known as the Curiously Recurring Template Pattern, and I don't think it's what you're looking for.  

    My guess is that you don't really mean to restrict the type of T at all.
    David Morton - http://blog.davemorton.net/
    Thursday, March 5, 2009 5:49 PM
  • Fantastic answer!!
    I think I understand.


    Basically the original code was as this ,then it was modified and created that "recursive restriction "
     public abstract class BaseEntity<T> : BaseEntity<T>, INotifyPropertyChanging, INotifyPropertyChanged   
                                            where T : BaseDataType<T> 



    I suppose if i remove the 

    where T : BaseEntity<T>  that should work no?

    Thanks again  for your very thorough reply.


    Thanks for your help
    Thursday, March 5, 2009 6:01 PM
  • It should work.  I'd remove any constraints on T that match the type of the class you're declaring.  So in the following example, you'll want to remove the constraint:

    public class BaseData<T> where T : BaseData<T>
    David Morton - http://blog.davemorton.net/
    • Marked as answer by devBrix Friday, March 6, 2009 1:14 PM
    Thursday, March 5, 2009 6:06 PM
  • Considering i have the following as it stands now.

     
     
      public abstract class BaseData<T> where T : BaseData<T> 
     {  
     }  
     
        public abstract class BaseEntity<T> : BaseData<T>, INotifyPropertyChanging, INotifyPropertyChanged 
        where T : BaseEntity
    <T> 
    {  
    What the end results should be? Sorry not that clear.

    I am a bit worried as there are 100s of classes inherithing from this.

    thanks again
    Thanks for your help
    Thursday, March 5, 2009 6:13 PM
  • That completely depends on your architecture, unfortunately, so it's not a simple thing to answer.  My guess is that you should simply remove the line that says "where T : BaseEntity<T>", but I'm not sure what else you're doing in this class.  It's also possible that T itself is supposed to inherit BaseData<T> as opposed to the entire class BaseEntity<T> inheriting from it.  I'm simply not sure, and without knowing what your end goal is, it's hard to tell.

    How are you using the types defined as T within the class?  Are they being used as BaseData objects?  If so, it should be:

    public abstract class BaseEntity<T> : INotifyPropertyChanging, INotifyPropertyChanged where T : BaseData<T>
    {
        
    }

    And BaseData<T> should simply be:

    public abstract class BaseData<T>
    {
        
    }

    But again, that depends on what the T is used as within BaseData. 

    Of course, the "where T" statement might need to be remove from both classes, if T is a specific simple object that isn't going to inherit from either BaseData<T> or BaseEntity<T>. 

    As you can see, it's nearly impossible for me to tell you, because I don't know what your end result is supposed to be, and I'm not sure what the responsibilities and properties of BaseData<T> and BaseEntity<T> actually are.
    David Morton - http://blog.davemorton.net/
    Thursday, March 5, 2009 6:19 PM
  • Thanks .
    Let me digest it all and think about it and may be i could clarify or even solve this .
    Thanks a lot for now.REALLY APPRECCIATE YOUR HELP

    Thanks for your help
    Thursday, March 5, 2009 6:21 PM
  • Thanks a lot for your time yesterday,
    Removed the constraint and inheritance and all fine.
    Thanks
    Thanks for your help
    Friday, March 6, 2009 1:14 PM