I am working on a strange issue related to VB.NET and multiple generic interfaces. The class I have implements a generic interface twice by specifying two different generic type arguments. In an effort to find a solution to that question (listed below), I had an idea but couldn't find any resources to see if this is possible.
VB.NET Implement Mutliple Contravariant interface types
The MSDN documentation here: http://msdn.microsoft.com/en-us/library/d5x73970.aspx explains type constraint usage, which is helpful but not complete (or at least the language doesn't support what I want).
Normally a constraint is declared as:
Public Interface ICopiesFrom(Of TObject As Class)
Sub CopyFrom(ByVal data As TObject)
End Interface
But lets say I wanted to exclude a possible generic type argument instead of restrict to a subset.
Public Sub Interface ICopiesFrom(Of TObject Not As SpecificBadType)
Can this be done?
It would seem like: How to call a generic method with type constraints when the parameter doesn't have these constraints? is a duplicate, but my question is a bit different because I'd like compile-time support.
Edit:
Here is an example use case (were something like this possible):
'Ideally, the interface would have a definition like this
Public Interface ICopiesFrom(Of TModel As Not ISecureType)
Sub CopyFrom(ByVal data As TModel)
End Interface
'Target type to exclude
Public Interface ISecureType
Property AccountValue As Decimal
Property AccountNumber As String
End Interface
Public Class AccountModel
Public Overridable Property AccountCreated As DateTime
Public Overridable Property ReferredBy As Guid
End Class
Public Class DetailedAccountModel
Inherits AccountModel
Implements ISecureType
Public Property AccountNumber As String Implements ISecureType.AccountNumber
Public Property AccountValue As Decimal Implements ISecureType.AccountValue
End Class
Public Class ProfileModel
Public Property UserName As String
Public Property EmailAddress As String
Public Property PhoneNumber As String
End Class
Public Class User 'Composite representation for a view
Implements ICopiesFrom(Of ProfileModel)
Implements ICopiesFrom(Of AccountModel)
Public Property UserName As String
Public Property EmailAddress As String
Public Property PhoneNumber As String
Public Property AccountCreated As DateTime
Public Property ReferredBy As Guid
Public Overridable Overloads Sub CopyFrom(ByVal data As ProfileModel) Implements ICopiesFrom(Of ProfileModel).CopyFrom
If data IsNot Nothing Then
Me.UserName = data.UserName
Me.EmailAddress = data.EmailAddress
Me.PhoneNumber = data.PhoneNumber
End If
End Sub
Public Overridable Overloads Sub CopyFrom(ByVal data As AccountModel) Implements ICopiesFrom(Of AccountModel).CopyFrom
If data IsNot Nothing Then
Me.AccountCreated = data.AccountCreated
Me.ReferredBy = data.ReferredBy
End If
End Sub
Public Function AccountAge() As Double
Return (DateTime.Now - AccountCreated).TotalDays
End Function
End Class
In the above scenario, I would never want someone to be able to pass a DetailedAccountModel
into the User
class so that it could never "accidentally" be displayed and ideally this would be caught at compile time.
Any of the following would be an acceptable answer:
No, there isn't a way to do this. You can ask for it to be considered as a language feature, but I think the language creators feel that this would encourage people to write code that violates the Open/Closed Principle.
For example, you might know right now that there's a specific class that should not be used as a generic type, but what's to stop someone else from coming up with another type that you don't know about now. The fact that you're trying to exclude a particular type is a code smell that probably indicates there's another better way to approach the problem you're trying to solve. Perhaps you're using inheritance where you should be using composition. Perhaps you could benefit by Segregating your Interfaces, or using better Separation of Concerns. Maybe by not including this feature the language is actually helping us to write more maintainable code.