diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 8c56899..a88f6bc 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,16 @@
 Changelog
 ---------
 
+6.0.0b5 (Unreleased)
+********************
+
+Refactoring:
+
+* *Backwards-incompatible*: `DelimitedList` now requires that its input be a
+  string and always serializes as a string. It can still serialize and deserialize
+  using another field, e.g. `DelimitedList(Int())` is still valid and requires
+  that the values in the list parse as ints.
+
 6.0.0b4 (2020-01-28)
 ********************
 
diff --git a/src/webargs/fields.py b/src/webargs/fields.py
index 0d8d46b..fcdf05f 100644
--- a/src/webargs/fields.py
+++ b/src/webargs/fields.py
@@ -44,37 +44,35 @@ class Nested(ma.fields.Nested):
 
 
 class DelimitedList(ma.fields.List):
-    """Same as `marshmallow.fields.List`, except can load from either a list or
-    a delimited string (e.g. "foo,bar,baz").
+    """A field which is similar to a List, but takes its input as a delimited
+    string (e.g. "foo,bar,baz").
+
+    Like List, it can be given a nested field type which it will use to
+    de/serialize each element of the list.
 
     :param Field cls_or_instance: A field class or instance.
     :param str delimiter: Delimiter between values.
-    :param bool as_string: Dump values to string.
     """
 
+    default_error_messages = {"invalid": "Not a valid delimited list."}
     delimiter = ","
 
-    def __init__(self, cls_or_instance, delimiter=None, as_string=False, **kwargs):
+    def __init__(self, cls_or_instance, delimiter=None, **kwargs):
         self.delimiter = delimiter or self.delimiter
-        self.as_string = as_string
         super().__init__(cls_or_instance, **kwargs)
 
     def _serialize(self, value, attr, obj):
-        ret = super()._serialize(value, attr, obj)
-        if self.as_string:
-            return self.delimiter.join(format(each) for each in ret)
-        return ret
+        # serializing will start with List serialization, so that we correctly
+        # output lists of non-primitive types, e.g. DelimitedList(DateTime)
+        return self.delimiter.join(
+            format(each) for each in super()._serialize(value, attr, obj)
+        )
 
     def _deserialize(self, value, attr, data, **kwargs):
-        try:
-            ret = (
-                value
-                if ma.utils.is_iterable_but_not_string(value)
-                else value.split(self.delimiter)
-            )
-        except AttributeError:
+        # attempting to deserialize from a non-string source is an error
+        if not isinstance(value, (str, bytes)):
             if MARSHMALLOW_VERSION_INFO[0] < 3:
                 self.fail("invalid")
             else:
                 raise self.make_error("invalid")
-        return super()._deserialize(ret, attr, data, **kwargs)
+        return super()._deserialize(value.split(self.delimiter), attr, data, **kwargs)

diff --git a/tests/test_core.py b/tests/test_core.py
index 4ff341b..feef0c1 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -835,21 +835,6 @@ def test_delimited_list_default_delimiter(web_request, parser):
     parsed = parser.parse(schema, web_request)
     assert parsed["ids"] == [1, 2, 3]
 
-    dumped = schema.dump(parsed)
-    data = dumped.data if MARSHMALLOW_VERSION_INFO[0] < 3 else dumped
-    assert data["ids"] == [1, 2, 3]
-
-
-def test_delimited_list_as_string(web_request, parser):
-    web_request.json = {"ids": "1,2,3"}
-    schema_cls = dict2schema(
-        {"ids": fields.DelimitedList(fields.Int(), as_string=True)}
-    )
-    schema = schema_cls()
-
-    parsed = parser.parse(schema, web_request)
-    assert parsed["ids"] == [1, 2, 3]
-
     dumped = schema.dump(parsed)
     data = dumped.data if MARSHMALLOW_VERSION_INFO[0] < 3 else dumped
     assert data["ids"] == "1,2,3"
@@ -858,11 +843,7 @@ def test_delimited_list_as_string(web_request, parser):
 def test_delimited_list_as_string_v2(web_request, parser):
     web_request.json = {"dates": "2018-11-01,2018-11-02"}
     schema_cls = dict2schema(
-        {
-            "dates": fields.DelimitedList(
-                fields.DateTime(format="%Y-%m-%d"), as_string=True
-            )
-        }
+        {"dates": fields.DelimitedList(fields.DateTime(format="%Y-%m-%d"))}
     )
     schema = schema_cls()
 
@@ -886,13 +867,17 @@ def test_delimited_list_custom_delimiter(web_request, parser):
     assert parsed["ids"] == [1, 2, 3]
 
 
-def test_delimited_list_load_list(web_request, parser):
+def test_delimited_list_load_list_errors(web_request, parser):
     web_request.json = {"ids": [1, 2, 3]}
     schema_cls = dict2schema({"ids": fields.DelimitedList(fields.Int())})
     schema = schema_cls()
 
-    parsed = parser.parse(schema, web_request)
-    assert parsed["ids"] == [1, 2, 3]
+    with pytest.raises(ValidationError) as excinfo:
+        parser.parse(schema, web_request)
+    exc = excinfo.value
+    assert isinstance(exc, ValidationError)
+    errors = exc.args[0]
+    assert errors["ids"] == ["Not a valid delimited list."]
 
 
 # Regresion test for https://github.com/marshmallow-code/webargs/issues/149
@@ -903,7 +888,7 @@ def test_delimited_list_passed_invalid_type(web_request, parser):
 
     with pytest.raises(ValidationError) as excinfo:
         parser.parse(schema, web_request)
-    assert excinfo.value.messages == {"ids": ["Not a valid list."]}
+    assert excinfo.value.messages == {"ids": ["Not a valid delimited list."]}
 
 
 def test_missing_list_argument_not_in_parsed_result(web_request, parser):

RFC: Only accept delimited string in DelimitedList
`DelimitedList` accepts either a list or a delimited string (e.g. "foo,bar,baz").

I'd like to make it more strict by only accepting a delimited list. Rather than adding a `strict` parameter, I'm thinking of dropping the whole "also accept a list" feature.

Any reason to support both?

I understand it inherits from `List` because once the string is parsed, it can be deserialized as a normal list. But are there cases where you'd expect either a list or a delimited string?
tests/test_core.py::test_delimited_list_default_delimiter tests/test_core.py::test_delimited_list_as_string_v2 tests/test_core.py::test_delimited_list_load_list_errors tests/test_core.py::test_delimited_list_passed_invalid_type
tests/test_core.py::test_load_json_called_by_parse_default tests/test_core.py::test_load_nondefault_called_by_parse_with_location[querystring] tests/test_core.py::test_load_nondefault_called_by_parse_with_location[form] tests/test_core.py::test_load_nondefault_called_by_parse_with_location[headers] tests/test_core.py::test_load_nondefault_called_by_parse_with_location[cookies] tests/test_core.py::test_load_nondefault_called_by_parse_with_location[files] tests/test_core.py::test_parse tests/test_core.py::test_parse_with_unknown_behavior_specified tests/test_core.py::test_parse_required_arg_raises_validation_error tests/test_core.py::test_arg_not_required_excluded_in_parsed_output tests/test_core.py::test_arg_allow_none tests/test_core.py::test_parse_required_arg tests/test_core.py::test_parse_required_list tests/test_core.py::test_parse_list_allow_none tests/test_core.py::test_parse_list_dont_allow_none tests/test_core.py::test_parse_empty_list tests/test_core.py::test_parse_missing_list tests/test_core.py::test_default_location tests/test_core.py::test_missing_with_default tests/test_core.py::test_default_can_be_none tests/test_core.py::test_arg_with_default_and_location tests/test_core.py::test_value_error_raised_if_parse_called_with_invalid_location tests/test_core.py::test_handle_error_called_when_parsing_raises_error tests/test_core.py::test_handle_error_reraises_errors tests/test_core.py::test_location_as_init_argument tests/test_core.py::test_custom_error_handler tests/test_core.py::test_custom_error_handler_decorator tests/test_core.py::test_custom_location_loader tests/test_core.py::test_custom_location_loader_with_data_key tests/test_core.py::test_full_input_validation tests/test_core.py::test_full_input_validation_with_multiple_validators tests/test_core.py::test_required_with_custom_error tests/test_core.py::test_required_with_custom_error_and_validation_error tests/test_core.py::test_full_input_validator_receives_nonascii_input tests/test_core.py::test_invalid_argument_for_validate tests/test_core.py::test_multidict_proxy[input_dict0] tests/test_core.py::test_multidict_proxy[input_dict1] tests/test_core.py::test_multidict_proxy[input_dict2] tests/test_core.py::test_parse_with_data_key tests/test_core.py::test_parse_with_data_key_retains_field_name_in_error tests/test_core.py::test_parse_nested_with_data_key tests/test_core.py::test_parse_nested_with_missing_key_and_data_key tests/test_core.py::test_parse_nested_with_default tests/test_core.py::test_nested_many tests/test_core.py::test_use_args tests/test_core.py::test_use_args_stacked tests/test_core.py::test_use_kwargs_stacked tests/test_core.py::test_decorators_dont_change_docstring[use_args] tests/test_core.py::test_decorators_dont_change_docstring[use_kwargs] tests/test_core.py::test_list_allowed_missing tests/test_core.py::test_int_list_allowed_missing tests/test_core.py::test_multiple_arg_required_with_int_conversion tests/test_core.py::test_parse_with_callable tests/test_core.py::test_use_args_callable tests/test_core.py::TestPassingSchema::test_passing_schema_to_parse tests/test_core.py::TestPassingSchema::test_use_args_can_be_passed_a_schema tests/test_core.py::TestPassingSchema::test_passing_schema_factory_to_parse tests/test_core.py::TestPassingSchema::test_use_args_can_be_passed_a_schema_factory tests/test_core.py::TestPassingSchema::test_use_kwargs_can_be_passed_a_schema tests/test_core.py::TestPassingSchema::test_use_kwargs_can_be_passed_a_schema_factory tests/test_core.py::TestPassingSchema::test_use_kwargs_stacked tests/test_core.py::TestPassingSchema::test_parse_does_not_add_missing_values_to_schema_validator tests/test_core.py::test_use_args_with_custom_location_in_parser tests/test_core.py::test_use_kwargs tests/test_core.py::test_use_kwargs_with_arg_missing tests/test_core.py::test_delimited_list_custom_delimiter tests/test_core.py::test_missing_list_argument_not_in_parsed_result tests/test_core.py::test_type_conversion_with_multiple_required tests/test_core.py::test_validation_errors_in_validator_are_passed_to_handle_error tests/test_core.py::test_parse_basic tests/test_core.py::test_parse_raises_validation_error_if_data_invalid tests/test_core.py::test_dict2schema tests/test_core.py::test_dict2schema_doesnt_add_to_class_registry tests/test_core.py::test_dict2schema_with_nesting tests/test_core.py::test_is_json tests/test_core.py::test_get_mimetype tests/test_core.py::test_parse_with_error_status_code_and_headers tests/test_core.py::test_custom_schema_class tests/test_core.py::test_custom_default_schema_class