I can't inherit the idea of Nothing from Vb.net code. but I wish to declare a list type in a if statement e.g.
Var LabourUnits;//does not work
if (LabourLinesFor == "Quote")
{
LabourUnits = context.QuoteLabourUnitsViews.Where(x => x.QuoteId == RelatedId).OrderBy(x => x.DisplayOrder).ToList();
ShowDiscounts = context.QuoteLabourUnitsViews.Where(x => x.QuoteId == RelatedId && x.UnitDiscountExVat > 0).Any();
VATPercent = default;
}
else if (LabourLinesFor == "Refund")
{
LabourUnits = context.RefundLabourUnitsViews.Where(x => x.RefundId == RelatedId).ToList();
VATPercent = context.RefundsViews.Where(x => x.RefundId == RelatedId).Select(x => x.Vatpercent).FirstOrDefault();
}
if(LabourUnits.Count > 0)
{
//do something
}
as the type is declared in the if statement it does not feed out to the outer var, and therefore cannot be used. Is there a way of creating a blank or carrier List? Updated Have used a real example, in vb LabourUnits could be declared as nothing but would then be accessible
further the VB -
Dim LabourUnits = Nothing
If LabourLinesFor = "Quote" Then
LabourUnits = dal.dc.QuoteLabourUnitsViews.Where(Function(x) x.QuoteID = RelatedID).OrderBy(Function(x) x.DisplayOrder).ToList
ShowDiscounts = dal.dc.QuoteLabourUnitsViews.Where(Function(x) x.QuoteID = RelatedID And x.UnitDiscountExVat > 0).Any
VATPercent = CType(Nothing, Decimal?)
ElseIf LabourLinesFor = "Refund" Then
LabourUnits = dal.dc.RefundLabourUnitsViews.Where(Function(x) x.RefundID = RelatedID).ToList
VATPercent = dal.dc.RefundsViews.Where(Function(x) x.RefundID = RelatedID).Select(Function(x) x.VATPercent).FirstOrDefault
End If
If LabourUnits.Count > 0 Then
'do something
End If
Failed attempt...
List<JobLabourUnitsView> jLabourUnits = new();
List<QuoteLabourUnitsView> qLabourUnits=new();
List<RefundLabourUnitsView> rLabourUnits = new();
List<PartsOnlyLabourView> pLabourUnits = new();
List<JobLabourUnitsView> prevLabourUnits = new();
decimal? VATPercent = default;
var ShowDiscounts = default(bool);
if (Preview)
{
prevLabourUnits = GetPreviewLabourUnits();
}
else if (LabourLinesFor == "Job")
{
jLabourUnits = context.JobLabourUnitsViews.Where(x => x.JobId == RelatedId).OrderBy(x => x.DisplayOrder).ToList();
ShowDiscounts = context.JobLabourUnitsViews.Where(x => x.JobId == RelatedId && x.UnitDiscountExVat > 0).Any();
VATPercent = context.TblJobs.Where(x => x.JobId == RelatedId).Select(x => x.Vatpercent).FirstOrDefault();
}
else if (LabourLinesFor == "Quote")
{
qLabourUnits = context.QuoteLabourUnitsViews.Where(x => x.QuoteId == RelatedId).OrderBy(x => x.DisplayOrder).ToList();
ShowDiscounts = context.QuoteLabourUnitsViews.Where(x => x.QuoteId == RelatedId && x.UnitDiscountExVat > 0).Any();
VATPercent = default;
}
else if (LabourLinesFor == "Refund")
{
rLabourUnits = context.RefundLabourUnitsViews.Where(x => x.RefundId == RelatedId).ToList();
VATPercent = context.RefundsViews.Where(x => x.RefundId == RelatedId).Select(x => x.Vatpercent).FirstOrDefault();
}
else if (LabourLinesFor == "PartsOnlySale")
{
pLabourUnits = context.PartsOnlyLabourViews.Where(x => x.PartsOnlySaleId == RelatedId).OrderBy(x => x.DisplayOrder).ToList();
ShowDiscounts = context.PartsOnlyLabourViews.Where(x => x.PartsOnlySaleId == RelatedId && x.UnitDiscountExVat > 0).Any();
VATPercent = context.TblPartsOnlySales.Where(x => x.PartsOnlySaleId == RelatedId).Select(x => x.Vatpercent).FirstOrDefault();
}
else if (LabourLinesFor == "CarSale")
{
}
Object[] obj = {
new { key = "0", value = jLabourUnits},
new { key = "1", value = qLabourUnits},
new { key = "2", value = rLabourUnits},
new { key = "3", value = pLabourUnits},
new { key = "4", value = prevLabourUnits}
};
int ticky = 0;
Type mod;
if(jLabourUnits.Count() > 0)
{
ticky = 0;
mod = (Type)Activator.CreateInstance(typeof(JobLabourUnitsView));
}
else if(qLabourUnits.Count() > 0)
{
ticky = 1;
mod = (Type)Activator.CreateInstance(typeof(QuoteLabourUnitsView));
}
else if(rLabourUnits.Count() > 0){
ticky = 2;
mod = (Type)Activator.CreateInstance(typeof(RefundLabourUnitsView));
}
else if(pLabourUnits.Count() > 0){
ticky = 3;
mod = (Type)Activator.CreateInstance(typeof(PartsOnlyLabourView));
}
else if(prevLabourUnits.Count() > 0){
ticky = 4;
mod = (Type)Activator.CreateInstance(typeof(JobLabourUnitsView));
}
IList<mod> LabourUnits = obj[ticky];
if (LabourUnits.Count() > 0)
//do something
This is totally unpleasant and doesn't work but as you can see have tried lateral methods...
CodePudding user response:
As Damien pointed out, you need to specify the type. If you use 'var' keyword, you can't leave the variable uninitialized.
var list; // will not work, the type is not known
List<string> list2; // will work, the type is clear
In this case, I would create a List<Interface>
or List<AbstractClass>
and then depending on what I need, have the list contain one or another object of a class that implement this interface or inherit from the abstract class.
List<IFruit> fruits = new();
fruits.Add(new Apple());
fruits.Add(new Orange());
interface IFruit { }
class Apple : IFruit { }
class Orange : IFruit { }
CodePudding user response:
I'm not sure that you fully understand what's going on in the VB or the C#, so I'll go over it all.
In VB, Option Strict
determines whether strict typing is enforced (On
) or not (Off
). Option Strict Off
is the default, to make things easier for beginners and VB6 developers but a good VB.NET developer will turn it On
immediately and leave it On
in all but those cases where late-binding is required, e.g. Office Automation. Even then, it should be On
at the project level and Off
at the file level for only those files that require it. Partial classes should be used to keep the amount of code in those files to an absolute minimum.
With Option Strict Off
, you can do this in VB:
Dim someVariable
In that case, someVariable
defaults to type Object
. That code is functionally equivalent to this:
Dim someVariable As Object
With Option Strict On
and strict typing enforced, the second code snippet would be required.
With the introduction of Option Infer
, variable data types can now be inferred from an initialising expression. Whether Option Strict
is On
or Off
, with Option Infer On
you can do this:
Dim someVariable = someExpression
and the data type of someVariable
will be inferred from the type of someExpression
, rather than defaulting to Object
. In C#, the use of var
works the same way, inferring the variable type from the initialising expression. This means that var
only makes sense when there is such an expression. This is valid C# code: Option Strict
is On
or Off
, with Option Infer On
you can do this:
var someVariable = someExpression;
but this makes no sense:
var someVariable;
With Option Strict Off
in VB, late binding is allowed. That means that the compiler will allow you to specify member access on an Object
reference that it cannot confirm and it is up to you to ensure that the actual object at run time has the specified member. This is allowed with Option Strict Off
:
Dim someVariable As Object = "Hello World"
Dim someOtherVariable
someOtherVariable = "Hello World"
Dim x Integer = someVariable.Length
Dim y Integer = someOtherVariable.Length
With Option Strict On
, that code would not compile. In C#, you can get basically the same functionality using dynamic
:
dynamic someVariable = "Hello World";
dynamic someOtherVariable;
someOtherVariable = "Hello World";
int x = someVariable.Length;
int y = someOtherVariable.Length;
Again, though, you should not be using dynamic
all over the place because you can't be bothered to write good strongly-typed code. It should be used where it adds genuine value.
In your case, if the reason you want to use a single variable is to use the Count
property then you can go for the lowest common denominator, which would be ICollection
. Any List<T>
can be assigned to a variable of that type, as can arrays and various other collections. ICollection
exposes a Count
property and it extends IEnumerable
, so you can run a foreach
loop over it too. If you use IList
instead then you can also index the list to get or set an item as well as Add
, Remove
and so on.
Using any of those interfaces, each item will be an Object
reference, so you cannot do anything that is specific to the item type. You could do anything with an item that wasn't common to all possible types anyway, which you could do if you were to have each item type implement the same interface.
If you want any more than that, you're going to have to explain what you actually want to achieve by using the same variable for different types of lists. You've shown the use of Count
and I've covered that. is there anything relevant that you didn't actually explain in your question?