perf/minor performance improvement in `is_*_dtype` and `get_block_type` methods
Improvements:
* use of `classes` in `is_*_dtype` avoid duplicate calls and will use a slightly simpler codepath in `isinstance` when possible
* `get_block_type` has unnecessary assignment removed - benchmarks added

- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [x] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.
- [x] Check performance change with `asv`

`asv continuous -f 1.1 main HEAD -b 'dtypes.CheckGetBlockType|dtypes.CheckDtypes'`:
```
     <main>           <perf/cache-typing>
-        548±40ns          481±2ns     0.88  dtypes.CheckGetBlockType.time_get_block_type('DatetimeLikeBlock')
-        604±30ns          497±3ns     0.82  dtypes.CheckGetBlockType.time_get_block_type('NumericBlock')
-        602±20ns         479±10ns     0.80  dtypes.CheckGetBlockType.time_get_block_type('ExtensionBlock')
-        358±10ns          279±2ns     0.78  dtypes.CheckGetBlockType.time_get_block_type('CategoricalBlock')
-        653±20ns          500±4ns     0.77  dtypes.CheckGetBlockType.time_get_block_type('ObjectBlock')
-        616±20ns          238±3ns     0.39  dtypes.CheckGetBlockType.time_get_block_type('sparse-ExtensionBlock')
SOME BENCHMARKS HAVE CHANGED SIGNIFICANTLY.
PERFORMANCE INCREASED.
```

 * _lesson learned:_ some places in the code can use `type(dtype)` instead of `dtype`, so would be reasonably suitable for caching, but it looks like the complexity of that code is sufficiently low that adding caching (particularly via `@lru_cache(n)` which has a fairly costly implementation) causes a slowdown if applied in an untargeted way. Maybe the odd place could benefit from extracting the `isinstance(dtype, str)` branch in `ExtensionDtype.is_dtype` into a method which can be cached internally, but I haven't followed that line of enquiery as performance generally seems good enough with the unfurling in this branch
 * _Trivia:_ the codebase has improved over time as `__isinstance__` overrides have been removed, but prior to that (e.g. 1.1) those were quite slow - this change was originally inspired by finding slowness from those and `cls.construct_from_string(...)`
Could you split this in 2 PR, 1 for typing and 1 for caching?

Also the whatsnew note should go in `v2.0.0.rst`. > Could you split this in 2 PR, 1 for typing and 1 for caching?
> 
> Also the whatsnew note should go in `v2.0.0.rst`.

I've stripped out caching as it generally wasn't beneficial, but left a note on https://github.com/pandas-dev/pandas/issues/48212#issuecomment-1288145916 about what where might be good to pursue for further gains without losses. > So generally this PR should be typing only? If so, could you undo all the refactoring?

Oh right, I thought you meant separating some bits in different modules. Is there some policy around type annotation additions? I originally added some after the pre-commit hook/CI complained about typing,

The `get_block_type` annotation just moves the type from internally to externally, and the refinement on `classes*` appear trivial, and that's all that is left in after simplifying the change. Accidentally closed and bodged editing of previous message while trying to walk and type at the same time Typically typing PRs don't involve a lot of refactoring of code - mainly just adding annotations.

Since this PR involves benchmark & whatsnew & typing annotations & refactoring, it would be preferable if this pull requests only targets one item at a time. @Code0x58 can you merge main and address comments Thanks for the pull request, but it appears to have gone stale. If interested in continuing, please merge in the main branch, address any review comments and/or failing tests, and we can reopen.