0

I'm designing a data layer for several classes, and I want each of these classes to follow a contract I set up with IMyDataItem:

public delegate void ItemChangedHandler(object sender, EventArgs e);

public interface IMyDataItem<T> {
  string Insert { get; }
  int Save();
  string Select { get; }
  string Update { get; }
}

That being done, I now want to include a base class that my other classes all inherit from.

How would I fix this base class?

public class MyDataItem : IMyDataItem<T> {

  private const string TODO = "TODO: This has not been done.";
  public const int NOT_SET = -1;

  private bool changed;
  internal int rowId;

  public MyDataItem() {
    changed = false;
    rowId = NOT_SET;
  }

  public ItemChangedHandler OnChange;

  internal void notify() {
    changed = true;
    if (OnChange != null) {
      OnChange(this, new EventArgs());
    }
  }

  public int RowID {
    get { return rowId; }
    set {
      if (rowId != value) {
        rowId = value;
        notify();
      }
    }
  }

  public bool SaveNeeded { get { return changed; } }

  public static virtual T Load() {
    return default(T);
  }

  public virtual string Insert { get { return TODO; } }

  public virtual string Select { get { return TODO; } }

  public virtual string Update { get { return TODO; } }

  public virtual int Save() {
    changed = false;
    return NOT_SET;
  }
}

The errors are all in the second class MyDataItem (my base class):

  • Type or namespace name 'T' could not be found - on the first line where I declare my class.

I tried removing the errors by adding a where clause to the signature:

public class MyDataItem : IMyDataItem<T> where T : MyDataItem {

However, this presented me with the error:

  • Constraints are not allowed on non-generic declarations

Is there a way to do what I am after, or will I need to stick with simpler class designs?

When the base class is complete, other classes such as Location, Employee, and Record will inherit it.

3
  • 2
    Such a large question for such a simple answer. Commented Aug 5, 2012 at 20:06
  • And still devdigital says he needs more information. Commented Aug 5, 2012 at 20:33
  • Well, it is odd that you have declared a generic interface that doesn't apparently need to be generic. Commented Aug 6, 2012 at 10:34

4 Answers 4

4

Well to fix that particularly compile time error you would need:

public class MyDataItem<T> : IMyDataItem<T>

However, without knowing more about what you're trying to achieve, it's hard to recommend an alternative approach.

Sign up to request clarification or add additional context in comments.

1 Comment

My other classes that are going to Inherit from this base class will have some of the code already written. This design is to ensure I don't forget a step and that I use the same language (or coding terms) throughout my code.
2

Why not drop the <T> from the interface and make it non-generic? The T is not used in the interface.

Otherwise, if you want the class to be generic, say

public class MyDataItem<T> : IMyDataItem<T>

But again, if T is not used, what's your reason to declare it?

9 Comments

My static Load command needs to know what type to return. Is there a simpler way?
Your static method cannot be declared virtual. You could make the class generic (class MyDataItem<T>), or you could make the method generic public static T Load<T>() { ... }.
I'm just noticing that, Jeppe. If I used public static T Load<T>(), would I be able to populate the data for different types?
I'm not sure how you want to use it. Right now, it just returns default(T) (which typically means zero for value types, and is just null for reference types), and that does not seem useful. Maybe you want it to be an instance method (remove static)? Then it can be marked virtual (or even abstract if you make the class abstract).
@jp2code I don't see Load taking an ID as paramter? But worse, I don't think a static method can use polymorphism like that. For the same reason a static method can't be virtual. Maybe it's easier to just use a normal instance constructor in each case?
|
1

What you are attempting to do is somewhat similar to what I've also done. I've wanted some generic code applicable to all my "data manager" instances but also wanted to apply stronger typing to them... In a similar fashion...

public interface iMyDataManager
{  
   stuff ... 
}

public class MyDataManager<T> : iMyDataManager
{  
   implementation ... that I want common to all derived specific instances 
}


public class MySpecificDataInstance : MyDataManager<MySpecificDataInstance>
{
   continue with rest of actual implementations specific to this class.
}

1 Comment

Yes, that is exactly what I am doing. It never makes sense to me when I read an example full of Foo and Bar.
0

I did not see any reason use generic in your implementation. Secondary, are you sure about parameters of these functions:

  string Insert { get; }
  int Save();
  string Select { get; }
  string Update { get; }

Why Update and Insert returns parameters? Are you sure, you will able remember meaning of this within 2 months?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.