Consume Equals instead of Contains - vb.net

I got two following class:
Class Part:
Imports System.Collections.Generic
Public Class Part
Implements IEqualityComparer(Of Part)
Public Sub New()
End Sub
Public Property _comparisonType As EqualsComparmission
Public Sub New(ComparisonType As EqualsComparmission)
Me._comparisonType = ComparisonType
End Sub
Public Property PartName() As String
Public Property PartId() As Integer
Public Function Equals1(x As Part, y As Part) As Boolean Implements System.Collections.Generic.IEqualityComparer(Of Part).Equals
If x Is Nothing AndAlso y Is Nothing Then Return True
If x Is Nothing OrElse y Is Nothing Then Return False
Select Case _comparisonType
Case EqualsComparmission.PartId
Return x.PartId = y.PartId
Case EqualsComparmission.PartName
Return String.Equals(x.PartName, y.PartName)
Case EqualsComparmission.PartId_and_PartName
Return x.PartId = y.PartId AndAlso String.Equals(x.PartName, y.PartName)
Case Else
Throw New NotSupportedException("Unknown comparison type for parts: " & _comparisonType.ToString())
End Select
End Function
Public Function GetHashCode1(obj As Part) As Integer Implements System.Collections.Generic.IEqualityComparer(Of Part).GetHashCode
Select Case _comparisonType
Case EqualsComparmission.PartId
Return obj.PartId
Case EqualsComparmission.PartName
Return If(obj.PartName Is Nothing, 0, obj.PartName.GetHashCode())
Case EqualsComparmission.PartId_and_PartName
Dim hash = 17
hash = hash * 23 + obj.PartId
hash = hash * 23 + If(obj.PartName Is Nothing, 0, obj.PartName.GetHashCode())
Return hash
Case Else
Throw New NotSupportedException("Unknown comparison type for parts: " & _comparisonType.ToString())
End Select
End Function
Public Overrides Function ToString() As String
Return "ID: " & PartId & " Name: " & PartName
End Function
End Class
Class PartCollection:
Public Class PartsCollection
Implements ICollection(Of Part)
Public Property _comparisonType As EqualsComparmission
Private myList As List(Of Part)
Public Sub New()
If myList Is Nothing Then
myList = New List(Of Part)
End If
End Sub
Public Sub New(ComparisonType As EqualsComparmission)
If myList Is Nothing Then
myList = New List(Of Part)
End If
Me._comparisonType = ComparisonType
End Sub
Public Sub Add(item As Part) Implements ICollection(Of Part).Add
myList.Add(item)
End Sub
Public Sub Clear() Implements ICollection(Of Part).Clear
myList.Clear()
End Sub
Public Sub CopyTo(array() As Part, arrayIndex As Integer) Implements ICollection(Of Part).CopyTo
End Sub
Public Function GetEnumerator() As IEnumerator(Of Part) Implements IEnumerable(Of Part).GetEnumerator
Return New PartsEnumeration(myList)
End Function
Public ReadOnly Property Count As Integer Implements ICollection(Of Part).Count
Get
Return myList.Count
End Get
End Property
Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of Part).IsReadOnly
Get
Return False
End Get
End Property
Public Function Remove(item As Part) As Boolean Implements ICollection(Of Part).Remove
Return myList.Remove(item)
End Function
Public Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
Return New PartsEnumeration(myList)
End Function
Public Function Contains(item As Part) As Boolean Implements ICollection(Of Part).Contains
Select Case _comparisonType
Case EqualsComparmission.PartId
Return myList.Exists(Function(x) x.PartId = item.PartId)
Case EqualsComparmission.PartName
Return myList.Exists(Function(x) x.PartName = item.PartName)
Case EqualsComparmission.PartId_and_PartName
Return myList.Exists(Function(x) x.PartId = item.PartId And x.PartName = item.PartName)
Case Else
Throw New NotSupportedException("Unknown comparison type for parts: " & _comparisonType.ToString())
End Select
End Function
End Class
I would like to use Equals1 from Part class instead as code is doing right now and using Contains1 from PartsCollection. I would like to ask you what i have to do in this case? My current code is working but i would like to switch to Equals1 as i created it earlier.
This is test code:
Dim myParts As New PartsCollection
Dim John As New Part With { _
.PartName = "John", _
.PartId = 1 _
}
Dim Silva As New Part With { _
.PartName = "Silva", _
.PartId = 2 _
}
Dim Jimmy As New Part With { _
.PartName = "Jimmy", _
.PartId = 3 _
}
Dim James As New Part With { _
.PartName = "James", _
.PartId = 4 _
}
myParts.Add(John)
myParts.Add(Silva)
myParts.Add(Jimmy)
myParts.Add(James)
Console.WriteLine("SEARCHING FOR CONCRETE PART IF EXIST")
myParts._comparisonType = EqualsComparmission.PartId_and_PartName
Dim p As Boolean = myParts.Contains(New Part() With { _
.PartName = "James", _
.PartId = 45 _
})

The reason for having functionality in one place or another is usually based on where it is needed or most useful rather than when it was written. You can of course, copy the code to whereever you like.
One problem in the current state is that you are have what should be a method argument defined as a Property. The comparisonType will need to be set each time you use it so that you can be sure it is set to what it should be. Secondly, since it is critical to the compare operation, you should want to see what is being used.
Calling Equals/Contains or whatever else on the collection class does not rule out using the method on the item class. To use it from a collection class:
Public Overloads Function Contains(p As Part,
compare As EqualsComparmission) As Boolean
Dim query = Items.Where(Function(f) p.Equals(f, compare)).ToList
Return query.Count <> 0
End Function
Usage:
If myParts.Contains(newP, EqualsComparmission.PartId_and_PartName) Then
The functionality for comparing exists in the Part Item class, the collection simply calls it. This also allows you to do:
If part1.Equals(part2)
The more important thing to note is that the comparison mode to use is passed as an argument, specifying which mode to use for this comparison. The actual query used would depend on what you need to know.

Related

Why is this returning Index out of bound exception

When I get to the Read loop I get an index out of bounds error. I think its on the reader ordinal value, but I am not sure why I am getting it.
Private Function Create(Reader As SqlDataReader) As IEnumerable(Of MyObject)
SetOrdinals(MyObjectReader)
Dim MyObjects = New List(Of MyObject)
While MyObjectReader.Read()
Dim Temp = New MyObject() With {
.FirstValue = MyObjectReader.GetValue(Of Integer)(MyObjectReader(FirstValue_Ord)),
.SecondValue = If(MyObjectReader.GetValue(Of String)(MyObjectReader(SecondValue_Ord)), String.Empty).Trim(),
.ThirdValue = If(MyObjectReader.GetValue(Of String)(MyObjectReader(ThirdValue_Ord)), String.Empty).Trim(),
MyObjects.Add(Temp)
End While
Return MyObjects
End Function
Private Sub SetOrdinals(MyObjectReader As SqlDataReader)
FirstValueOrd = MyObjectReader.GetOrdinal("FirstValue")
SecondValue_Ord = MyObjectReader.GetOrdinal("SecondValue")
ThirdValue_Ord = MyObjectReader.GetOrdinal("ThirdValue")
End Sub
End Class
Public Module Extensions
<Extension>
Function GetValue(Of T)(rdr As SqlDataReader, i As Integer) As T
If rdr.IsDBNull(i) Then
Return Nothing
End If
Return DirectCast(rdr.GetValue(i), T)
End Function
End Module
You should just be passing in the ordinal to the GetValue calls:
While MyObjectReader.Read()
Dim Temp = New MyObject() With {
.FirstValue = MyObjectReader.GetValue(Of Integer)(FirstValue_Ord),
.SecondValue = If(MyObjectReader.GetValue(Of String)(SecondValue_Ord), String.Empty).Trim(),
.ThirdValue = If(MyObjectReader.GetValue(Of String)(ThirdValue_Ord), String.Empty).Trim()
}
MyObjects.Add(Temp)
End While
Here my version :)
Private Function Create(reader As SqlDataReader) As IEnumerable(Of MyObject)
Dim objects As New List(Of MyObject)()
Dim ordinals As New Ordinals(reader)
While reader.Read()
Dim Temp As New MyObject With
{
.FirstValue = reader.GetValueOrDefault(Of Integer)(ordinals.FirstValue),
.SecondValue = reader.GetValueOrDefault(ordinals.SecondValue, "").Trim(),
.ThirdValue = reader.GetValueOrDefault(ordinals.ThirdValue, "").Trim()
}
objects.Add(Temp)
End While
Return MyObjects
End Function
Private Class Ordinals
Public Property FirstValue As Integer
Public Property SecondValue As Integer
Public Property ThirdValue As Integer
Public Sub New(reader As SqlDataReader)
FirstValue = reader.GetOrdinal(nameOf(FirstValue))
SecondValue = reader.GetOrdinal(nameOf(SecondValue))
ThirdValue = reader.GetOrdinal(nameOf(ThirdValue))
End Sub
End Class
Public Module Extensions
<Extension>
Function GetValueOrDefault(Of T)(reader As SqlDataReader, ordinal As Integer) As T
Return reader.GetValueOrDefault(Of T)(ordinal, Nothing)
End Function
<Extension>
Function GetValueOrDefault(Of T)(reader As SqlDataReader,
ordinal As Integer,
defaultValue As T) As T
Dim value = reader(ordinal)
If value = DbNull.Value Then
Return defaultValue
End If
Return DirectCast(value, T)
End Function
End Module
Because extension method execute checking for DbNull.Value against already extracted object, we get rid from reading same value twice from SqlDataReader.
SqlDataReader.IsDbNull(index) reads value before checking for DbNull.
Extension method have two overloads:
- One which return default value of given type, if value is DbNull.Value. Nothing in vb.net is default value of type.
- And one which takes parameter for default value you want return if value is DbNull.Value. Possibility pass default value makes lines where you create new object shorter and more readable. We get rid of inline if statement.
Your extension method with name GetValue have "side effects". By name consumer of this method expect to get value from SqlDataReader. So he can expect to get DbNull.Value if database query return NULL, but instead he get null for string or 0 for integer. Name GetValueOrDefault is little bid more informative, so you don't need to go inside method to check what is doing.

How to use GetType and GetFields?

I'm updating a program and there is about 40 classes. I need to create a function that takes two lists of type object as parameters. Both lists only have one item in them (A version of the item BEFORE any changes were made, and AFTER the changes happened). I'm using these objects to create a single object to implement an UNDO button. With these parameters I need to get the type of each and make sure they match, if not then something went wrong. Next I'll need to read in the fields/properties/members (Not sure what to choose) and then compare them to each other and find what changed so I can set that as the item description. I don't want to trace the whole code and add specific functions for each and I know there has got to be a way to do this generically. I have created this small mock-up program that semi works for what I am trying to do. I can get the class type out of the object in list, but i have no idea how to get fields or whatever.
I'm using a large database with entity framework.
Also Using VB.NET!
Thanks for the help!
Here's code for generic program:
Imports System.Reflection
Module Module1
Sub Main()
Dim Myself As New Human("Matthew", "Cucco", Now, "Blonde", 19, False)
Dim NotMe As New Human("Jake", "Cucco", Now, "Blonde", 19, False)
Dim Him As New Employee("Matt", "Cucco", Now, "Blonde", 19, False, 215, "LuK", True)
Dim Her As New Customer("Jessie", "Keller", Now, "Blonde", 19, True, 25, "Cereal", "me#gmail.com")
Dim ListofPeople As IList(Of Object) = {Myself, NotMe, Him, Her}
Dim ListofPeople2 As IList(Of Object) = {Myself, NotMe, Him, Her}
ObjectsAreSameClass(ListofPeople, ListofPeople2)
Console.ReadKey()
End Sub
Private Function ObjectsAreSameClass(object1 As IList(Of Object), object2 As IList(Of Object)) As Boolean
Dim ObjectType As Type = object1.First.GetType()
Dim AreSameClass As Boolean = Nothing
Console.WriteLine(ObjectType.ToString)
If (object1.First.GetType() = object2.First.GetType()) Then
AreSameClass = True
Console.WriteLine("Object1 is of type: " + object1.First.GetType().Name)
Console.WriteLine("Object2 is of type: " + object2.First.GetType().Name)
If (object1.First.GetType().Name = "Human") Then
Console.WriteLine("Yep this works")
End If
Else
AreSameClass = False
Console.WriteLine("Object1 is of type: " + object1.First.GetType().Name)
Console.WriteLine("Object2 is of type: " + object2.First.GetType().Name)
If (object1.First.GetType().Name = "Human") Then
Console.WriteLine("Yep this works")
Console.WriteLine(object1.First.GetType().GetFields().ToString)
End If
End If
Dim MyField As PropertyInfo() = ObjectType.GetProperties()
Dim i As Integer
For i = 0 To MyField.Length - 1
Console.WriteLine(MyField(i).ToString)
Next i
Console.WriteLine("Objects are equal? t/f : " + AreSameClass.ToString)
Return AreSameClass
End Function
Public Class Human
Public FirstName As String
Public LastName As String
Public Birthdate As Date
Public HairColor As String
Public Age As Integer
Public Gender As Boolean 'False for male, true for female
Public Sub New()
FirstName = ""
LastName = ""
Birthdate = Now
HairColor = ""
Age = 0
Gender = False
End Sub
Public Sub New(f As String, l As String, b As Date, h As String, a As Integer, g As Boolean)
FirstName = f
LastName = l
Birthdate = b
HairColor = h
Age = a
Gender = g
End Sub
End Class
Public Class Employee
Inherits Human
Dim EmployeeId As Integer
Dim PlaceOfEmployment As String
Dim IsManager As Boolean
Public Sub New()
MyBase.New()
EmployeeId = 0
PlaceOfEmployment = ""
IsManager = False
End Sub
Public Sub New(f As String, l As String, b As Date, h As String, a As Integer, g As Boolean, i As Integer, p As String, m As Boolean)
MyBase.New(f, l, b, h, a, g)
EmployeeId = i
PlaceOfEmployment = p
IsManager = m
End Sub
End Class
Public Class Customer
Inherits Human
'used for testing
Dim IdNumber As Integer
Dim FavoriteItem As String
Dim email As String
Public Sub New()
MyBase.New()
IdNumber = 0
FavoriteItem = ""
email = ""
End Sub
Public Sub New(f As String, l As String, b As Date, h As String, a As Integer, g As Boolean, i As Integer, fav As String, e As String)
MyBase.New(f, l, b, h, a, g)
IdNumber = i
FavoriteItem = fav
email = e
End Sub
End Class
End Module
This Currently displays this:
TestProject.Module1+Human
Object1 is of type: Human
Object2 is of type: Human
Yep this works
Objects are equal? t/f : True
Also for reference, here is my main program that I will be implementing this into:
Function NewItem(Before As IEnumerable(Of Object), After As IEnumerable(Of Object), ObjectType As String)
ObjectsAreSameClass(Before, After, ObjectType) 'Check if objects are same class
Dim BeforeFields() As FieldInfo = GetFieldData(Before) 'gets all field info, saves to an array
Dim AfterFields() As FieldInfo = GetFieldData(After)
'Now check and make sure the objects are not the same
Dim ThisChanged As FieldInfo
If (ObjectValuesAreEqual(BeforeFields, AfterFields) = True) Then
'These objects did not not change
ThisChanged = Nothing
Else
'Change occured, find out where
ThisChanged = FindWhatChanged(BeforeFields, AfterFields)
End If
'Create a new UndoRedo item and give it these values
Dim UndoRedoNow As New ClsUndoRedo
UndoRedoNow.BeforeObject = Before.Single
UndoRedoNow.AfterObject = After.Single
UndoRedoNow.ObjectCounter += 1
UndoRedoNow.WhatChanged = ThisChanged
If WhatGroupChanged.isDeleted Then
UndoRedoNow.WhatAction = Before.Single.GetType().ToString + " item was Deleted"
ElseIf WhatGroupChanged.isNew Then
UndoRedoNow.WhatAction = After.Single.GetType().ToString + " item was created"
ElseIf WhatGroupChanged.isChanged Then
UndoRedoNow.WhatAction = After.Single.GetType().ToString + " item was changed"
End If
UndoRedoNow.WhatGroupChanged.isRedo = False 'Make sure it is not a redo object
'Now add object to list
ChangeLog.Add(UndoRedoNow)
Return Nothing
End Function
Private Function ObjectsAreSameClass(before As IEnumerable(Of Object), after As IEnumerable(Of Object), WhatType As String) As Boolean
Dim AreSameClass As Boolean = False
Try
If (before.Single.GetType() = after.Single.GetType() Or (before Is Nothing) Or (after Is Nothing)) Then
'Objects are of the same class or nothing
If before Is Nothing Then
WhatGroupChanged.isNew = True 'New item
ElseIf after Is Nothing Then
WhatGroupChanged.isDeleted = True 'Deleted item
Else
WhatGroupChanged.isChanged = True 'item was changed
End If
AreSameClass = True
End If
Catch
'Need to raise error
End Try
Return AreSameClass
End Function
''' <summary>
''' This function will return all of the fields for a certain class as well as the data stored in them
''' </summary>
''' <param name="list"></param>
''' <returns></returns>
Public Shared Function GetFieldData(ByVal list As IList(Of Object)) As FieldInfo()
Dim fields() As FieldInfo = list.Single.GetType().GetFields()
Return fields
End Function
''' <summary>
''' This function will check that the values in the datafields are not equal
''' </summary>
''' <param name="Before"></param>
''' <param name="After"></param>
''' <returns></returns>
Private Function ObjectValuesAreEqual(Before() As FieldInfo, After() As FieldInfo) As Boolean
Dim isEqual As Boolean = New Boolean 'This will keep track of if the elements are equal or not
For index As Integer = 0 To (Before.Count - 1)
If Before.ElementAt(index).GetValue(Before.ElementAt(index)).Equals(After.ElementAt(index).GetValue(After.ElementAt(index))) Then
'They are equal so set to true
isEqual = True
Else
'They are not equal so set to false and return
isEqual = False
Return isEqual
End If
Next
Return isEqual
End Function
Private Function FindWhatChanged(Before() As FieldInfo, After() As FieldInfo) As FieldInfo
Dim ThisIsChange As FieldInfo
For index As Integer = 0 To (Before.Count - 1)
If Before.ElementAt(index).GetValue(Before.ElementAt(index)).Equals(After.ElementAt(index).GetValue(After.ElementAt(index))) Then
ThisIsChange = After.ElementAt(index)
Return ThisIsChange
Else
'Raise error
End If
Next
End Function
The proper way to preserve type information when working with unknown types is to write a generic function (and if necessary generic classes, structures, etc.).
Using GetType, in a perfect world, should never be needed.
Generic functions look like this:
Public Function MyGenericFunction(Of T)(myArg as T) as Integer
' do something with myArg1, myArg2 ... without knowing their exact type
Return 0
End Function
' or with multiple types
Public Function MyGenericFunction2(Of T1, T2, ... )(myArg1 as T1, myArg2 as T2, ...) as T1()
' do something with myArg1, myArg2 ... without knowing their exact type
Return { myArg1 }
End Function
When you call these functions, the generic types are usually automatically deduced from the arguments you passed. If they can't be guessed, you will need to explicitly annotate the types, like this:
Dim x = MyGenericFunction(Of SomeClass1)(foo)
Dim x = MyGenericFunction(Of SomeClass2)(foo)
A full guide here: https://msdn.microsoft.com/en-us/library/w256ka79.aspx
However, if you need to handle specific types with the same function, then what you want to do use is a more narrow tool: overloading, or more technically parametric polymorphism.
What that means is, you will need to provide two (or more) different definitions of the same function ( = having the same name), that accept parameters of different types.
A simple example:
Public Class MyClass1
Public Foo1 As String = "foo1"
End Class
Public Class MyClass2
Public Foo2 As String = "foo2"
End Class
Public Sub MyFunction(arg as MyClass1)
Console.WriteLine(arg.Foo1)
End Sub
Public Sub MyFunction(arg as MyClass2)
Console.WriteLine(arg.Foo2)
End Sub
Dim x as Object
' let's give x a random value of either MyClass1 or MyClass2,
' and we don't know in advance which one
If DateTime.Today.DayOfWeek = DayOfWeek.Tuesday Then
x = new MyClass1
Else
x = new MyClass2
End If
' the program will automatically invoke the correct function based on x's value, and print either "foo1" or "foo2"
MyFunction(x)

Is there a quick and efficient way to make classes equitable?

I have many classes with often many properties/fields of primitive types or array/nullable of primitive types.
Public Class ClassN
Public P1 As Integer
Public P2 As Byte()
Public P3 As String
Public P4 As Short?
'...
Public P17 As Boolean
Public P18 As Char()
End Class
At this point I've come up with a solution using attributes and a "equality service class" which performs the equality test. But is there a quicker and a more efficient way to implement this?
Code behind
<AttributeUsage((AttributeTargets.Field Or AttributeTargets.Property), AllowMultiple:=False, Inherited:=False)> _
Public Class EquatableAttribute
Inherits Attribute
End Class
Public Class ClassN
Implements IEquatable(Of ClassN)
<Equatable()> Public P1 As Integer
<Equatable()> Public P2 As Byte()
<Equatable()> Public P3 As String
<Equatable()> Public P4 As Short?
'...
<Equatable()> Public P17 As Boolean
<Equatable()> Public P18 As Char()
Public Overrides Function Equals(obj As Object) As Boolean
Return Me.Equals(TryCast(obj, ClassN))
End Function
Public Overloads Function Equals(obj As ClassN) As Boolean Implements System.IEquatable(Of ClassN).Equals
Return EqualityServices.Equals(Of ClassN)(Me, obj)
End Function
End Class
Public NotInheritable Class EqualityServices
Private Sub New()
End Sub
Public Overloads Shared Function Equals(Of T)(obj1 As T, obj2 As T) As Boolean
If (obj1 Is Nothing) Then
Return obj2 Is Nothing
End If
If (obj2 Is Nothing) Then
Return False
End If
Dim type As Type = GetType(T)
Dim members As MemberInfo() = Nothing
If (Not EqualityServices.EquatableAttributeCache.TryGetValue(type, members)) Then
members = New MemberInfo(-1) {}
For Each info As MemberInfo In type.GetMembers((BindingFlags.Public Or BindingFlags.Instance))
If (info.GetCustomAttributes(EqualityServices.EquatableAttributeType, False).Length > 0) Then
Select Case info.MemberType
Case MemberTypes.Field
Exit Select
Case MemberTypes.Property
With DirectCast(info, PropertyInfo)
If ((Not .CanRead) OrElse (.GetIndexParameters().Length > 0)) Then
Continue For
End If
End With
Exit Select
Case Else
Continue For
End Select
ReDim Preserve members(members.Length)
members(members.Length - 1) = info
End If
Next
EqualityServices.EquatableAttributeCache.Add(type, members)
End If
If (members.Length > 0) Then
Dim value1 As Object = Nothing
Dim value2 As Object = Nothing
For Each info As MemberInfo In members
Select Case info.MemberType
Case MemberTypes.Field
With DirectCast(info, FieldInfo)
type = .FieldType
value1 = .GetValue(obj1)
value2 = .GetValue(obj2)
End With
Exit Select
Case MemberTypes.Property
With DirectCast(info, PropertyInfo)
type = .PropertyType
value1 = .GetValue(obj1, Nothing)
value2 = .GetValue(obj2, Nothing)
End With
Exit Select
Case Else
Continue For
End Select
If (type.BaseType Is EqualityServices.ArrayType) Then
If (Not EqualityServices.SequenceEqual(CType(value1, Array), CType(value2, Array))) Then
Return False
End If
Else
If (Not Object.Equals(value1, value2)) Then
Return False
End If
End If
Next
Return True
End If
Return False
End Function
Private Shared Function SequenceEqual(ByVal array1 As Array, array2 As Array) As Boolean
If (array1 Is Nothing) Then
Return array2 Is Nothing
End If
If (array2 Is Nothing) Then
Return False
End If
If (array1.Rank <> array2.Rank) Then
Return False
End If
If (array1.Length <> array2.Length) Then
Return False
End If
Dim length As Integer = (array1.Length - 1)
If (length > -1) Then
Dim list1 As IList = CType(array1, IList)
Dim list2 As IList = CType(array2, IList)
For index = 0 To length
If (Not Object.Equals(list1.Item(index), list2.Item(index))) Then
Return False
End If
Next
End If
Return True
End Function
Private Shared ReadOnly EquatableAttributeCache As New Dictionary(Of Type, MemberInfo())
Private Shared ReadOnly EquatableAttributeType As Type = GetType(EquatableAttribute)
Private Shared ReadOnly ArrayType As Type = GetType(Array)
End Class
ReSharper can generate the relevant Equals, GetHashCode, etc. or an IEqualityComparer code for you.
You just, well, need ReSharper.
Here's an example (it's C# because I only have the C#-Edition of ReSharper at hand):

VB: Problems with using variable from another class + what to do with not used interface`s functions

I have a problem with getting variable from another class and cannot understand what to do with interface`s functions which have already existed in another class.
What I have:
Form where clicking on a button I should see reversed string:
(I want to call pooraja.StringReverse which is below)
Private Sub btnPoora1_Click(sender As System.Object, e As System.EventArgs) _
Handles btnPoora1.Click
'Dim text As PrjTekstiPooraja.ITeisendused = New PrjTekstiPooraja.CtekstiPooraja
Dim text As PrjTekstiPooraja.ITeisendused = New PrjTekstiPooraja.CtekstiPooraja
Dim pooraja As PrjTekstiPooraja.ITeisendused = New PrjTekstiPooraja.CAlgrotimilinePooraja
text.strText = txtSisendTekst.Text
txtValjundTekst1.Text = pooraja.stringReverse
text.intStart = 1
text.intEnd = Len(txtSisendTekst.Text)
ascFSymbol.Text = text.ascFirstSymbol
ascLSymbol.Text = text.ascLastSymbol()
End Sub
CtekstiPooraja:
(Thiss class will be used to store data.Under data I mean strPooratavText. Data will be used in CAlgoritmilinePooraja)
Public Class CtekstiPooraja
Implements ITeisendused
Public intStartSymbol As Integer
Public intEndSymbol As Integer
Public strPooratavText As String
Private Property intEnd As Integer Implements ITeisendused.intEnd
Get
Return intEndSymbol
End Get
Set(ByVal value As Integer)
intEndSymbol = value
End Set
End Property
Private Property intStart As Integer Implements ITeisendused.intStart
Get
Return intStartSymbol
End Get
Set(ByVal value As Integer)
intStartSymbol = value
End Set
End Property
Public Function pooraText() As String Implements ITeisendused.pooraText
Return StrReverse(strPooratavText)
End Function
Public Property strText As String Implements ITeisendused.strText
Get
Return strPooratavText
End Get
Set(ByVal value As String)
strPooratavText = value
MsgBox(strPooratavText)
End Set
End Property
Public Sub teisendaText(ByRef strSisendText As String) Implements ITeisendused.teisendaText
strPooratavText = StrReverse(strSisendText)
End Sub
Public Function ascFirstSymbol() As String Implements ITeisendused.ascFirstSymbol
Return Asc(GetChar(strPooratavText, intStartSymbol))
End Function
Public Function ascLastSymbol() As String Implements ITeisendused.ascLastSymbol
Return Asc(GetChar(strPooratavText, intEndSymbol))
End Function
Public Function stringReverse() As String Implements ITeisendused.stringReverse
Return Nothing
End Function
End Class
CAlgrotimilinePooraja:
(This class will be called by form button. There I need to use stringReverse function with data from CtekstiPooraja. The problem is that everywhere is used the same interface and there is some functions and procedures from this interface which isnt necessary. I dont know what value should return these unused functions/procedures. Just using "return Nothing or return 0/ "" is bad idea, may be there is possible somehow referenceto to CTekstiPooraja functions/procedures variables")
Public Class CAlgrotimilinePooraja
Implements ITeisendused
Private x As New PrjTekstiPooraja.CtekstiPooraja
Public Function stringReverse() As String Implements ITeisendused.stringReverse
MsgBox(x.strPooratavText)
Dim i As Integer = 0
Dim j As Integer
Dim characters(j) As Char
Dim newString(j) As Char
characters = x.strPooratavText.ToCharArray()
newString = x.strPooratavText.ToCharArray()
Do While i <= j - 1
newString(i) = characters(j - 1)
newString(j - 1) = characters(i)
i += 1
j -= 1
Loop
Return newString
End Function
Public Function ascFirstSymbol() As String Implements ITeisendused.ascFirstSymbol
Return x.ascFirstSymbol()
End Function
Public Function ascLastSymbol() As String Implements ITeisendused.ascLastSymbol
Return Nothing
End Function
Public Property intEnd As Integer Implements ITeisendused.intEnd
Get
Return x.intEndSymbol
End Get
Set(ByVal value As Integer)
End Set
End Property
Public Property intStart As Integer Implements ITeisendused.intStart
Get
Return x.intStartSymbol
End Get
Set(ByVal value As Integer)
End Set
End Property
Public Function pooraText() As String Implements ITeisendused.pooraText
Return x.pooraText()
End Function
Public Property strText As String Implements ITeisendused.strText
Get
Return x.strPooratavText
End Get
Set(ByVal value As String)
End Set
End Property
Public Sub teisendaText(ByRef strSisendText As String) Implements ITeisendused.teisendaText
x.strPooratavText = StrReverse(strSisendText)
End Sub
End Class
MyInterface:
Public Interface ITeisendused
Property intStart As Integer
Property intEnd As Integer
Property strText As String
Function pooraText() As String
Function ascFirstSymbol() As String
Function ascLastSymbol() As String
Function stringReverse() As String
Sub teisendaText(ByRef strSisendText As String)
End Interface
I cannot understand how to get variable strPooratavText from CTekstiPooraja to CAlgrotimilinePooraja. Usually that instancewhich I create worked but not now. And I cannot understand what to do with already existed function and procedures in CAlgoritmilinePooraja when the same function and procedures has in another class. Maybe, it is possible to reference them somehow to existed functions/procedures in CTekstiPooraja? Could you explain me how to id, already tired to surf Internet to find a solution for it, have already try a lot.
Well, I think you have a fundamental problem with understanding interfaces. They describe data and behavior, it should be extremely rare to want to implement part of an interface.
That said, if you do want to implement part of an interface, instead of returning bogus data, throw an exception for behavior you don't implement.
Your specific problem is that CAlgoritmilinePooraja works on an instance of CtekstiPooraja, but it creates a new instance instead of using an existing one. Add
Sub New(incomingX as CtekstiPooraja)
x = incomingX
End Sub
to CAlgoritmilinePooraja. And then in your event, use....
Dim text As PrjTekstiPooraja.CtekstiPooraja = New PrjTekstiPooraja.CtekstiPooraja
text.strText = txtSisendTekst.Text
Dim pooraja As PrjTekstiPooraja.ITeisendused = New PrjTekstiPooraja.CAlgrotimilinePooraja(text)
That is the minimum change to your design that gets what you want to happen to happen but it's problably not what you should do. Other than implementing strReverse, CtekstiPooraja seems to be what you want, CAlgrotimilinePooraja looks to do just one thing, the actual string reversal.
I would move the implementation of strReverse into CtekstiPooraja, and then eliminate CAlgrotimilinePooraja.
PS I would try to stick to English for class names as well as functions and variables.

Error says x is not a member of y, but it is

I have a sp that I added to my linq designer, which generated the result class:
Partial Public Class web_GetTweetsByUserIDResult
Private _userid As Integer
Private _tweetid As Integer
Private _TweeterFeed As String
Public Sub New()
MyBase.New
End Sub
<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_userid", DbType:="Int NOT NULL")> _
Public Property userid() As Integer
Get
Return Me._userid
End Get
Set
If ((Me._userid = value) _
= false) Then
Me._userid = value
End If
End Set
End Property
<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_tweetid", DbType:="Int NOT NULL")> _
Public Property tweetid() As Integer
Get
Return Me._tweetid
End Get
Set
If ((Me._tweetid = value) _
= false) Then
Me._tweetid = value
End If
End Set
End Property
<Global.System.Data.Linq.Mapping.ColumnAttribute(Storage:="_TweeterFeed", DbType:="NVarChar(100)")> _
Public Property TweeterFeed() As String
Get
Return Me._TweeterFeed
End Get
Set
If (String.Equals(Me._TweeterFeed, value) = false) Then
Me._TweeterFeed = value
End If
End Set
End Property
End Class
However, in this one section of code where I am trying to use the "TweeterFeed" member of the result class I am getting the error, "Error 4 'TweeterFeed' is not a member of 'System.Data.Linq.ISingleResult(Of web_GetTweetsByUserIDResult)'."
My code in this section is, :
<WebMethod()> _
Public Function GetTweetsByUserID(ByVal userID As Integer) As List(Of SimpleTweet)
Dim result As New List(Of SimpleTweet)
Dim urlTwitter As String = "https://api.twitter.com/1/statuses/user_timeline.xml?include_entities=true&include_rts=true&screen_name={0}&count=20"
Dim lq As New lqDFDataContext
Dim var = lq.web_GetTweetsByUserID(userID).ToList()
If Not var Is Nothing Then
For Each twitterfeed In var
Dim listURL As String = String.Format(urlTwitter, var.TweeterFeed)
Dim tweetXML As XmlDocument = utils.GetXMLForURL(listURL)
Dim tweetnodelist As XmlNodeList = tweetXML.ChildNodes(1).ChildNodes
For Each node As XmlNode In tweetnodelist
Dim tweet As New SimpleTweet
tweet.CreatedAt = node.SelectSingleNode("created_at").InnerText
tweet.HTMLText = utils.ReturnTextWithHRefLink(node.SelectSingleNode("text").InnerText)
tweet.ID = node.SelectSingleNode("id").InnerText
tweet.Name = node.SelectSingleNode("user/name").InnerText
tweet.ScreenName = node.SelectSingleNode("user/screen_name").InnerText
tweet.Text = node.SelectSingleNode("text").InnerText
tweet.UserID = node.SelectSingleNode("user/id").InnerText
tweet.ProfileImageURL = node.SelectSingleNode("user/profile_image_url_https").InnerText
result.Add(tweet)
Next
Next
End If
Return result
End Function
Does anyone have any idea what is going on? As far as I see "TweeterFeed" is clearly a member of the class, I can't figure out why I would be getting this error.
You're using var.TweeterFeed when you should be using twitterFeed.TweeterFeed. twitterFeed is a result extracted from var which is a sequence of results.
Using a more descriptive variable name than var would probably have made this clearer to you :)
I have this class
Public Class Tamano
Private pWidth As Integer
Private pHeight As Integer
Public Property Width As Integer
Public Property Height As Integer
End Class
I got the compilation error message 'Height' is not a member of 'TamaƱo' in IIS
To fix it, add Set and Get to the properties and it compiles.
Public Class Tamano
Private pWidth As Integer
Private pHeight As Integer
Public Property Width As Integer
Get
Return pWidth
End Get
Set(value As Integer)
pWidth = value
End Set
End Property
Public Property Height As Integer
Get
Return pHeight
End Get
Set(value As Integer)
pHeight = value
End Set
End Property
End Class
This might not be directly related to your question but It might help someone else.