In C#, once a variable is declared, it keeps the type it's declared as.
With reference types, like string, the nullable syntax is only supported by attributes and inference at compile-time, so string? is effectively the same as string besides some compiler hints. This would allow syntax like yours to work if you were working with a reference type.
But with value types, like int, the nullable type is literally a completely different type at run-time, so the value needs to be extracted from an int? in order to treat it like an int. You have to use a completely different variable to hold a strongly-typed int? versus int. That might look something like this:
if (row != null) // or row.HasValue
{
int test = row.Value;
// use `test`
}
With newer pattern matching syntax, you can do this instead:
if (row is int test)
{
// use `test`
}